package com.authine.cloudpivot.ext.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.dto.RequestContext;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.common.organization.feign.OrganizationFeignService;
import com.authine.cloudpivot.ext.applicationservice.base.ApplicationBaseService;
import com.authine.cloudpivot.ext.constants.ApiClientConstants;
import com.authine.cloudpivot.ext.constants.AppConst;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.dto.OrderCustomerDto;
import com.authine.cloudpivot.ext.model.order.OrderGoodsAcceptVO;
import com.authine.cloudpivot.ext.model.order.OrderGoodsReturnsVO;
import com.authine.cloudpivot.ext.dto.OrderTraceDto;
import com.authine.cloudpivot.ext.dto.api.AgreeRefundVO;
import com.authine.cloudpivot.ext.dto.api.BulkRefundVO;
import com.authine.cloudpivot.ext.dto.finance.TradeErpPoUpdate;
import com.authine.cloudpivot.ext.dto.order.PlaceOrderSourcingDTO;
import com.authine.cloudpivot.ext.dto.order.StockBillMaterialDto;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.dto.system.RoleDto;
import com.authine.cloudpivot.ext.dto.system.UserDto;
import com.authine.cloudpivot.ext.dto.voucher.Voucher;
import com.authine.cloudpivot.ext.entity.goods.GoodsEntity;
import com.authine.cloudpivot.ext.entity.goods.GoodsPurchaseEntity;
import com.authine.cloudpivot.ext.entity.order.OrderGoodsRelationEntity;
import com.authine.cloudpivot.ext.entity.sourcingcenter.InquiryEntity;
import com.authine.cloudpivot.ext.entity.sourcingcenter.InquiryGoodsEntity;
import com.authine.cloudpivot.ext.enums.CartSrcEnum;
import com.authine.cloudpivot.ext.enums.ReviewStatusEnum;
import com.authine.cloudpivot.ext.enums.commoditymaterials.GoodsPurchaseTypeEnum;
import com.authine.cloudpivot.ext.enums.demandpool.DemandGoodsStatusEnum;
import com.authine.cloudpivot.ext.enums.demandpool.DemandPoolStatusEnum;
import com.authine.cloudpivot.ext.enums.finance.InvoiceStatusEnum;
import com.authine.cloudpivot.ext.enums.finance.PaymentStatusEnum;
import com.authine.cloudpivot.ext.enums.finance.ReconciliationStatusEnum;
import com.authine.cloudpivot.ext.enums.goods.GoodsType;
import com.authine.cloudpivot.ext.enums.order.*;
import com.authine.cloudpivot.ext.enums.order.transfer.OrderType;
import com.authine.cloudpivot.ext.enums.system.OrganizationAttributeEnum;
import com.authine.cloudpivot.ext.enums.system.RoleAdminEnum;
import com.authine.cloudpivot.ext.enums.trade.TradeDirection;
import com.authine.cloudpivot.ext.enums.trade.TradeInvoiceStatus;
import com.authine.cloudpivot.ext.field.OrderCenterTableField;
import com.authine.cloudpivot.ext.fun.ObjectFunction;
import com.authine.cloudpivot.ext.model.order.CustomerOrderGoodsVo;
import com.authine.cloudpivot.ext.service.DockFinanceService;
import com.authine.cloudpivot.ext.service.OrderCreateVoucher;
import com.authine.cloudpivot.ext.service.OrderService;
import com.authine.cloudpivot.ext.service.ZhendeService;
import com.authine.cloudpivot.ext.utils.*;
import com.authine.cloudpivot.ext.utils.boQuery.BoQueryUtils;
import com.authine.cloudpivot.ext.utils.message.MessageUtils;
import com.authine.cloudpivot.ext.utils.system.*;
import com.authine.cloudpivot.ext.vo.*;
import com.authine.cloudpivot.ext.vo.i.*;
import com.authine.cloudpivot.ext.vo.zhende.PushOrderGoodsModel;
import com.authine.cloudpivot.ext.vo.zhende.PushOrderModel;
import com.authine.cloudpivot.ext.vo.zhende.PushOrderUpdateModel;
import com.authine.hermes.app.launcher.service.WorkflowService;
import com.authine.mvp.app.launcher.common.SchemaHelper;
import com.authine.mvp.app.launcher.common.TableHelper;
import com.authine.mvp.app.launcher.domain.SelectorFormat;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.domain.utills.DateUtils;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;
import com.authine.mvp.app.launcher.utils.JsonParseObject;
import com.authine.mvp.app.org.dto.domainmodel.UnitType;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class OrderServiceImpl extends ApplicationBaseService implements OrderService {

    private final NamedParameterJdbcTemplate jdbcTemplate = ApplicationContextUtils.getBean(NamedParameterJdbcTemplate.class);
    private final OrganizationFeignService organizationFeignService = ApplicationContextUtils.getBean(OrganizationFeignService.class);
    private final TableHelper tableHelper = ApplicationContextUtils.getBean(TableHelper.class);

    private OrderCreateVoucher orderCreateVoucher = new OrderCreateVoucherImpl();
    WorkflowService workflowService = (WorkflowService) ApplicationContextUtils.getBean(WorkflowService.class);
    private ZhendeService zhendeService = new ZhendeServiceImpl();
    private final static DockFinanceService dockFinanceService = new DockFinanceServiceImpl();

    TransactionTemplate transactionTemplate = ApplicationContextUtils.getBean(TransactionTemplate.class);

    /**
     * 采购订单-批量修改客户订单状态（批量取消/批量付款/提交审批）
     *
     * @return
     * @throws RuntimeException
     */
    @Override
    public SingleResponse batchUpdateOrderCustomer(OrderCustomerDto dto) throws RuntimeException {
        if (CollectionUtils.isEmpty(dto.getIds()) || null == dto.getOrderCustomerStatus()) {
            return SingleResponse.buildFailure("-1", "参数为空");
        }
        OrderCustomerStatusEnum orderCustomerStatus = dto.getOrderCustomerStatus();
        if (null == orderCustomerStatus) {
            throw new RuntimeException("订单状态为空！");
        }
        //修改客户订单SQL
        Map<String, Object> customerUpdateMap = new HashMap<>();
        //修改供应商订单SQL
        Map<String, Object> vendorUpdateMap = new HashMap<>();
        //修改客户订单商品SQL
        Map<String, Object> customerGoodsUpdateMap = new HashMap<>();
        //修改供应商订单商品SQL
        Map<String, Object> vendorGoodsUpdateMap = new HashMap<>();
        //批量付款时：修改客户订单、供应商订单、订单商品状态为未接单，付款时间为当前时间，付款方式（目前只有信用付款）
        if (orderCustomerStatus.equals(OrderCustomerStatusEnum.UpcomingConfirm)) {
            String orderVendorStatus = OrderVendorStatusEnum.UpcomingConfirm.name();
            String orderGoodsStatus = OrderGoodsStatusEnum.UpcomingConfirm.name();
            customerUpdateMap.put("order_customer_status", orderCustomerStatus.name());
            customerUpdateMap.put("place_order_time", new Date());
            customerUpdateMap.put("payment_method", PaymentMethodEnum.Credit.name());
            vendorUpdateMap.put("order_vendor_status", orderVendorStatus);
            vendorUpdateMap.put("place_order_time", new Date());
            customerGoodsUpdateMap.put("order_customer_goods_status", orderGoodsStatus);
            customerGoodsUpdateMap.put("place_order_time", new Date());
            vendorGoodsUpdateMap.put("order_vendor_goods_status", orderGoodsStatus);
            vendorGoodsUpdateMap.put("place_order_time", new Date());
        }
        //批量付取消时：客户订单、供应商订单、订单商品状态修改为已关闭
        if (orderCustomerStatus.equals(OrderCustomerStatusEnum.Closed)) {
            String orderVendorStatus = OrderVendorStatusEnum.Closed.name();
            String orderGoodsStatus = OrderGoodsStatusEnum.Closed.name();
            customerUpdateMap.put("order_customer_status", orderCustomerStatus.name());
            vendorUpdateMap.put("order_vendor_status", orderVendorStatus);
            customerGoodsUpdateMap.put("order_customer_goods_status", orderGoodsStatus);
            vendorGoodsUpdateMap.put("order_vendor_goods_status", orderGoodsStatus);
        }
        //提交审批时(部分流程下单会走流程审批)：构建调用审批流程参数后直接调用流程审批（flowable）创建接口，然后修改客户订单表中的enabled=false
        if (orderCustomerStatus.equals(OrderCustomerStatusEnum.UpcomingPayment)) {
            //TODO 构建调用审批流程参数后直接调用流程审批（flowable）创建接口
            customerUpdateMap.put("enabled", false);
        }
        for (String id : dto.getIds()) {
            if (orderCustomerStatus.equals(OrderCustomerStatusEnum.UpcomingPayment)) {
                if (!CollectionUtils.isEmpty(customerUpdateMap)) {
                    JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).putFieldAndVal(customerUpdateMap).eq("id", id).update();
                }
            } else {
                if (!CollectionUtils.isEmpty(customerUpdateMap)) {
                    JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).putFieldAndVal(customerUpdateMap).eq("id", id).update();
                }
                if (!CollectionUtils.isEmpty(vendorUpdateMap)) {
                    JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR).putFieldAndVal(vendorUpdateMap).eq("order_customer_id", id).update();
                }
                if (!CollectionUtils.isEmpty(customerGoodsUpdateMap)) {
                    JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal(customerGoodsUpdateMap).eq("order_customer_id", id).update();
                }
                if (!CollectionUtils.isEmpty(vendorGoodsUpdateMap)) {
                    JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal(vendorGoodsUpdateMap).eq("order_customer_id", id).update();
                }
            }
        }
        //TODO 销售订单组织是否需要短信和邮件的通知
        //修改转采订单状态
        updateTransferOrderStatus(dto.getIds());
        //调用其他服务
        if (orderCustomerStatus.equals(OrderCustomerStatusEnum.UpcomingConfirm)) {
            //生成消息通知
            List<String> messageParams = dto.getIds().stream().map(t -> "客户订单号：" + t + " 付款成功！").collect(Collectors.toList());
            MessageUtils.createdSystemMessage(messageParams);

            //调用财务生成交易记录
            SingleResponse response = dockFinanceService.createTrade(dto.getIds());
        }
        return SingleResponse.of(true);
    }

    /**
     * 接单
     * cn/gomro/core/bizes/order/service/impl/OrdersService.orderTaking
     *
     * @param vendorOrderIds 供应商订单编号
     * @return
     * @throws
     */
    @Override
    public boolean orderTaking(List<String> vendorOrderIds) throws RuntimeException {
        if (null == vendorOrderIds || vendorOrderIds.isEmpty()) {
            throw new RuntimeException("参数为空");
        }
        Set<String> orderCustomerIds = new HashSet<>();
        for (String id : vendorOrderIds) {
            Map<String, Object> result = selectModelById(String.valueOf(id), ModelConst.T_ORDER_VENDOR);
            if (CollectionUtils.isEmpty(result)) {
                throw new RuntimeException("订单不存在");
            }
            String status = (String) result.get("order_vendor_status");
            if (!OrderGoodsStatusEnum.UpcomingConfirm.name().equals(status)) {
                throw new RuntimeException("订单状态必须为未接单，否则无法接单！");
            }
//            if (!result.get("after_sale").equals("未售后") && !result.get("after_sale").equals("已售后")) {
//                throw new RuntimeException("售后情况必须为未售后或已售后！");
//            }
            Map<String, Object> orderVendorParam = new HashMap<>();
            //设置接单人和接单时间
            SelectorFormat orderTakerSF = getSelectorFormat(null, UnitType.USER);
            //接单人
            orderVendorParam.put("order_taker_id", orderTakerSF);
            //接单人名称
            orderVendorParam.put("order_taker_name", orderTakerSF.getName());
            //接单时间
            orderVendorParam.put("confirm_order_time", new Date());
            orderVendorParam.put("order_vendor_status", OrderVendorStatusEnum.UpcomingDelivery.name());
            orderVendorParam.put("id", result.get("id"));
            SingleResponse<BO> bo = BoServiceUtils.updateMainBo(ModelConst.T_ORDER_VENDOR, orderVendorParam);
            //供应商接单订单商品的状态为待发货
            List<Map<String, Object>> vendorGoodsList = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS)
                    .selectField("*").eq("order_vendor_id", result.get("id")).queryForList();
            for (Map<String, Object> vendorGoodsMap : vendorGoodsList) {
                //期货
                Integer delivery = BigDecimalUtils.isNull(vendorGoodsMap.get("delivery")).intValue();
                Calendar c = Calendar.getInstance();
                c.setTime(new Date());
                if (0 == delivery || 7 >= delivery) {
                    c.add(Calendar.HOUR, 8);
                } else {
                    c.add(Calendar.DATE, delivery - 7);
                }
                //供应商接单订单商品的状态为待发货
                Map<String, Object> orderCustomerGoods = getOrderGoods(null, (String) vendorGoodsMap.get("id"));
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal("remind_time", c.getTime())
                        .putFieldAndVal("order_vendor_goods_status", OrderGoodsStatusEnum.UpcomingDelivery.name())
                        .eq("id", vendorGoodsMap.get("id")).update();
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal("remind_time", c.getTime())
                        .putFieldAndVal("order_customer_goods_status", OrderGoodsStatusEnum.UpcomingDelivery.name())
                        .eq("id", orderCustomerGoods.get("id")).update();
            }
            orderCustomerIds.add((String) result.get("order_customer_id"));
        }
        updateOrderStatus(new ArrayList<>(orderCustomerIds));
        return true;
    }

    /**
     * 供应商发货
     * cn/gomro/core/bizes/order/service/impl/OrdersService.orderTaking
     *
     * @param dto
     * @return
     * @throws RuntimeException
     */
    @Override
    public SingleResponse<BO> vendorDeliveryLogistics(OrderTraceDto dto) throws RuntimeException {
        if (CollectionUtils.isEmpty(dto.getOrderVendorGoodsIds()) || StringUtils.isBlank(dto.getOrderVendorId())) {
            return SingleResponse.buildFailure("-1", "订单供应商商品ID集合、订单供应商ID必填");
        }
        //可发货数
        BigDecimal deliverableNums = BigDecimal.ZERO;
        for (String orderVendorGoodsId : dto.getOrderVendorGoodsIds()) {
            BigDecimal deliverableNum = getDeliverableNum(orderVendorGoodsId);
            deliverableNums = BigDecimalUtils.add(deliverableNum, deliverableNums);
        }
        //发货数量
        BigDecimal deliveryNums = BigDecimal.ZERO;
        for (BigDecimal quantity : dto.getQuantitys()) {
            deliveryNums = BigDecimalUtils.add(quantity, deliveryNums);
        }
        //发货数据不能大于可发货数量
        if (deliveryNums.compareTo(deliverableNums) == 1) {
            throw new RuntimeException("发货数据不能大于可发货数量");
        }
        List<Map<String, Object>> listMap = new ArrayList<>();
        //如果供应商订单状态为未接单，需要进行调用接单接口
        Map<String, Object> orderVendor = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR).selectField("*")
                .eq("id", dto.getOrderVendorId()).queryForMap();
        if (!CollectionUtils.isEmpty(orderVendor) && orderVendor.get("order_vendor_status").equals(OrderGoodsStatusEnum.UpcomingConfirm.name())) {
            orderTaking(Collections.singletonList(dto.getOrderVendorId()));
        }
        //根据供应商订单所属组织性质是否为虚拟供应商时，拿供应商订单下所有商品ID调用转采服务是否生成转采订单，如果没有生成拒绝执行发货，并提示“未创建转采采购订单，无法进行发货
        List<SelectorFormat> organizationIdSF = JsonParseObject.parseObject((String) orderVendor.get("organization_id"), SelectorFormat.class);
        if (isVirtual(organizationIdSF.get(0))) {
            List<String> cloudDeliverGoods = getCloudDeliverGoods(dto.getOrderVendorGoodsIds());
            if (!cloudDeliverGoods.isEmpty()) {
                throw new RuntimeException("商品编号：" + cloudDeliverGoods + "，未创建转采采购订单，无法发货");
            }
        }
        //TODO 一采通接单消息推送，根据商品的供应商订单ID获取供应商订单.order_customer_id，获取客户订单表中的client_id和商品中的client_order_goods_id，进行消息推送
        //勾选多个商品发货则订单商品数据等于发货数量
        boolean isBatchDelivery = false;
        if (dto.getOrderVendorGoodsIds().size() > 1) {
            isBatchDelivery = true;
        }
        for (String orderVendorGoodsId : dto.getOrderVendorGoodsIds()) {
            //通过供应商商品ID获取客户商品信息
            Map<String, Object> orderCustomerGoods = getOrderGoods(null, orderVendorGoodsId);
            if (CollectionUtils.isEmpty(orderCustomerGoods)) {
                throw new RuntimeException("客户商品信息不存在！");
            }
            BigDecimal quantity = BigDecimal.ZERO;
            if (isBatchDelivery) {
                Map<String, Object> orderVendorGood = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).selectField("*").eq("id", orderVendorGoodsId).queryForMap();
                dto.setQuantitys(Collections.singletonList(BigDecimalUtils.isNull(orderVendorGood.get("quantity"))));
                quantity = BigDecimalUtils.add(quantity, BigDecimalUtils.isNull(orderVendorGood.get("quantity")));
            }
            for (int i = 0; i < dto.getQuantitys().size(); i++) {
                Map<String, Object> map = new HashMap<>();
                map.put("type", TraceTypeEnum.ShippingLogistics.toString());
                map.put("logistics", dto.getLogistics());
                map.put("freight", dto.getFreight());
                if (!CollectionUtils.isEmpty(dto.getWaybills())) {
                    map.put("waybill", dto.getWaybills().get(i));
                }
                map.put("arrival_time", dto.getArrivalTime());
                if (!CollectionUtils.isEmpty(dto.getQuantitys()) && !isBatchDelivery) {
                    map.put("quantity", BigDecimalUtils.round(dto.getQuantitys().get(i), 6));
                    quantity = BigDecimalUtils.add(quantity, dto.getQuantitys().get(i));
                } else {
                    map.put("quantity", BigDecimalUtils.round(quantity, 6));
                }
                map.put("order_vendor_goods_id", orderVendorGoodsId);
                map.put("order_customer_goods_id", orderCustomerGoods.get("id"));
                map.put("order_customer_id", orderCustomerGoods.get("order_customer_id"));
                map.put("order_vendor_id", orderCustomerGoods.get("order_vendor_id"));
                //其他字段赋值
                Object customer_organization_id = orderCustomerGoods.get("customer_organization_id");
                map.put("customer_organization_id", Objects.isNull(customer_organization_id) ? null : JSON.parseObject((String) customer_organization_id, SelectorFormat.class));
                map.put("customer_organization_name", orderCustomerGoods.get("customer_organization_name"));
                Object vendor_organization_id = orderCustomerGoods.get("customer_organization_id");
                map.put("vendor_organization_id", Objects.isNull(vendor_organization_id) ? null : JSON.parseObject((String) vendor_organization_id, SelectorFormat.class));
                SelectorFormat send = getSelectorFormat(null, UnitType.USER);
                map.put("sender_id", send);
                map.put("sender_fullname", send.getName());
                Object place_order_user_id = orderCustomerGoods.get("place_order_user_id");
                map.put("recipient_id", Objects.isNull(place_order_user_id) ? null : JSON.parseObject((String) place_order_user_id, SelectorFormat.class));
                map.put("recipient_fullname", orderCustomerGoods.get("place_order_fullname"));
                map.put("quantity_received", BigDecimalUtils.round(BigDecimalUtils.isNull(orderCustomerGoods.get("quantity_received")), 6));
                map.put("name", orderCustomerGoods.get("name"));
                map.put("quantity_unit", BigDecimalUtils.round(BigDecimalUtils.isNull(map.get("quantity")), 0) + "/" + orderCustomerGoods.get("unit"));
                listMap.add(map);
            }
            Map<String, Object> orderVendorGoodsParam = new HashMap<>();
            Map<String, Object> orderCustomerGoodsParam = new HashMap<>();
            //更新供应商订单商品和库户订单商品为已发货,已发货数量更新
            Map<String, Object> orderVendorGoodsMap = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).selectField("*").eq("id", orderVendorGoodsId).queryForMap();
            quantity = BigDecimalUtils.add(quantity, BigDecimalUtils.isNull(orderVendorGoodsMap.get("quantity_shipped")));

            orderVendorGoodsParam.put("order_vendor_goods_status", OrderGoodsStatusEnum.DoneDelivery.name());
            orderCustomerGoodsParam.put("order_customer_goods_status", OrderGoodsStatusEnum.DoneDelivery.name());
            orderVendorGoodsParam.put("quantity_shipped", quantity);
            orderCustomerGoodsParam.put("quantity_shipped", quantity);
            JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal(orderVendorGoodsParam).eq("id", orderVendorGoodsId).update();
            JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal(orderCustomerGoodsParam).eq("id", orderCustomerGoods.get("id")).update();
        }
        //修改订单状态
        updateOrderStatus(Collections.singletonList((String) orderVendor.get("order_customer_id")));
        SingleResponse<BO> bo = BoServiceUtils.createBo(ModelConst.T_ORDER_TRACE, listMap);
        return bo;
    }

    /**
     * 根据订单商品ID查询可以发货的商品
     *
     * @param cloudOrderGoods
     * @return
     */
    public List<String> getCloudDeliverGoods(List<String> cloudOrderGoods) {

        List<String> goodsIds = new ArrayList<>();
        Map<String, Object> param = new HashMap<>();
        param.put("cloud_order_goods_id", cloudOrderGoods);

        StringBuilder sql = new StringBuilder("SELECT GROUP_CONCAT( DISTINCT t.cloud_order_goods_id||'',',') AS cloud_order_goods_id  \n")
                .append("FROM   zhuancai.i_zhuancai_t_member_purchase_goods AS g \n")
                .append("LEFT JOIN i_ordercenter_t_member_purchase_order AS m ON m.id = g.member_purchase_order_id  \n")
                .append("left join zhuancai.i_zhuancai_t_transfer_order_goods as t on  t.id=g.transfer_order_goods_id  \n")
                .append("left join  zhuancai.i_zhuancai_t_transfer_order as o  on  o.id=t.transfer_order_id    \n")
                .append("WHERE g.deleted = FALSE  and o.order_type is null AND  m.deleted = FALSE and m.is_rp<>true  and m.status in (2,3,4)  ")
                .append("and t.cloud_order_goods_id IN (:cloud_order_goods_id) group  by g.transfer_order_goods_id");

        List<Map<String, Object>> allowedDeliverGoods = jdbcTemplate.queryForList(sql.toString(), param);
        if (null != allowedDeliverGoods) {
            List<String> ids = new ArrayList<>();
            for (Map<String, Object> map : allowedDeliverGoods) {
                ids.add((String) map.get("cloud_order_goods_id"));
            }

            for (int i = 0; i < cloudOrderGoods.size(); i++) {
                if (!ids.contains(cloudOrderGoods.get(i))) {
                    goodsIds.add(cloudOrderGoods.get(i));
                }
            }
        }
        return goodsIds;
    }


    /**
     * 修改供应商订单、客户订单状态、供应商商品和客户商品状态(同一个订单下)
     *
     * @param customerOrderIds 客户订单ID集合
     */
    public void updateOrderStatus(List<String> customerOrderIds) {
        if (CollectionUtils.isEmpty(customerOrderIds)) {
            return;
        }
        OrderVendorStatusEnum orderVendorStatus = null;
        OrderCustomerStatusEnum orderCustomerStatus = null;
        List<Map<String, Object>> writeBackParams = new ArrayList<>();
        //查询供应商订单商品
        List<Map<String, Object>> orderVendorGoods = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS)
                .selectField("*").in("order_customer_id", customerOrderIds).queryForList();
        for (Map<String, Object> orderVendorGood : orderVendorGoods) {
            //供应商商品状态
            OrderGoodsStatusEnum orderVendorGoodsStatus = null;
            OrderGoodsStatusEnum orderCustomerGoodsStatus = null;
            Map<String, Object> orderVendor = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR)
                    .selectField("*").in("id", orderVendorGood.get("order_vendor_id")).queryForMap();
            //通过供应商商品ID获取客户商品信息
            Map<String, Object> orderCustomerGoods = getOrderGoods(null, (String) orderVendorGood.get("id"));
            //1.已发货数量为0并且供应商订单状态为交易中，则修改为未发货
            if (BigDecimalUtils.isNull(orderVendorGood.get("quantity_shipped")).compareTo(BigDecimal.ZERO) == 0
                    && orderVendor.get("order_vendor_status").equals(OrderVendorStatusEnum.UpcomingConfirm)) {
                orderVendorGoodsStatus = OrderGoodsStatusEnum.UpcomingDelivery;
                orderCustomerGoodsStatus = OrderGoodsStatusEnum.UpcomingDelivery;
            }
            //可发数量
            BigDecimal deliverableNum = this.getDeliverableNum((String) orderVendorGood.get("id"));
            //可收数量
            BigDecimal enableNum = this.getEnableNum((String) orderCustomerGoods.get("id"));
            //可退货数量
            BigDecimal refundableNum = this.getRefundableNum((String) orderCustomerGoods.get("id"));
            if (!CollectionUtils.isEmpty(orderCustomerGoods)) {
                //3.（已发货数量>0并且可发货数量不为0）或（可发货数量为0并且可收货数量>0），则修改为已发货
                if ((BigDecimalUtils.isNull(orderVendorGood.get("quantity_shipped")).compareTo(BigDecimal.ZERO) == 1 && deliverableNum.compareTo(BigDecimal.ZERO) != 0) ||
                        (deliverableNum.compareTo(BigDecimal.ZERO) == 0 && enableNum.compareTo(BigDecimal.ZERO) == 1)) {
                    orderVendorGoodsStatus = OrderGoodsStatusEnum.DoneDelivery;
                    orderCustomerGoodsStatus = OrderGoodsStatusEnum.DoneDelivery;
                }
            }
            //2.可发货数量为0并且可收货数量为0时并且可退货数量!=0，则修改为已完成
            if (deliverableNum.compareTo(BigDecimal.ZERO) == 0 && enableNum.compareTo(BigDecimal.ZERO) == 0 && refundableNum.compareTo(BigDecimal.ZERO) != 0) {
                orderVendorGoodsStatus = OrderGoodsStatusEnum.Done;
                orderCustomerGoodsStatus = OrderGoodsStatusEnum.Done;
            }
            //更新供应商订单商品状态
            if (null != orderVendorGoodsStatus) {
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal("order_vendor_goods_status", orderVendorGoodsStatus.name())
                        .eq("id", orderVendorGood.get("id")).update();
            }
            Map<String, Object> orderCustomerGood = getOrderGoods(null, (String) orderVendorGood.get("id"));
            //更新客户订单商品状态
            if (null != orderCustomerGoodsStatus) {
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal("order_customer_goods_status", orderCustomerGoodsStatus.name())
                        .eq("id", orderCustomerGood.get("id")).update();
            }
            //回写订单对应交易的订单商品状态
            List<Map<String, Object>> orderGoodsReturns = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURNS).selectField("*").eq("order_vendor_goods_id", orderVendorGood.get("id"))
                    .sort("createdTime desc").queryForList();
            Map<String, Object> writeBackParam = new HashMap<>();
            writeBackParam.put("orderGoodsId", orderCustomerGood.get("id"));
            writeBackParam.put("orderGoodsStatus", null != orderCustomerGoodsStatus ? orderCustomerGoodsStatus.name() : orderCustomerGood.get("order_customer_goods_status"));
            writeBackParam.put("orderGoodsReturnsStatus", CollectionUtils.isEmpty(orderGoodsReturns) ? null : orderGoodsReturns.get(0).get("order_goods_returns_status"));
            writeBackParams.add(writeBackParam);
        }

        List<Map<String, Object>> orderVendorGoodsNew = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS)
                .selectField("*").in("order_customer_id", customerOrderIds).queryForList();
        List<String> orderVendorGoodsStatusList = orderVendorGoodsNew.stream().map(t -> (String) t.get("order_vendor_goods_status")).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(orderVendorGoodsStatusList)) {
            //全部商品为未发货==单据则为未发货
            if (orderVendorGoodsStatusList.stream().allMatch(t -> t.equals(OrderGoodsStatusEnum.UpcomingDelivery.name()))) {
                orderVendorStatus = OrderVendorStatusEnum.UpcomingDelivery;
            }
            //只要有一个商品为已发货==单据则为已发货
            if (orderVendorGoodsStatusList.stream().anyMatch(t -> t.equals(OrderGoodsStatusEnum.DoneDelivery.name()))) {
                orderVendorStatus = OrderVendorStatusEnum.DoneDelivery;
            }
            //全部商品为已关闭==单据则为已关闭
            if (orderVendorGoodsStatusList.stream().allMatch(t -> t.equals(OrderGoodsStatusEnum.Closed.name()))) {
                orderVendorStatus = OrderVendorStatusEnum.Closed;
            }
            //全部商品为已完成或一个或多个商品已完成其余全都是已关闭==单据则为已完成
            if (orderVendorGoodsStatusList.stream().allMatch(t -> t.equals(OrderGoodsStatusEnum.Done.name()))) {
                orderVendorStatus = OrderVendorStatusEnum.Done;
            }
            List<String> result = orderVendorGoodsStatusList.stream().filter(t -> t.equals(OrderGoodsStatusEnum.Done.name())).collect(Collectors.toList());
            if (orderVendorGoodsStatusList.size() > 0 && result.size() == orderVendorGoodsStatusList.size()) {
                orderVendorStatus = OrderVendorStatusEnum.Done;
            }
            //更新供应商订单状态
            for (String customerOrderId : customerOrderIds) {
                if (null != orderVendorStatus) {
                    JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR).putFieldAndVal("order_vendor_status", orderVendorStatus.name())
                            .eq("order_customer_id", customerOrderId).update();
                }
            }
        }

        List<Map<String, Object>> orderVendorNew = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR)
                .selectField("*").in("order_customer_id", customerOrderIds).queryForList();
        List<String> orderVendorStatusList = orderVendorNew.stream().map(t -> (String) t.get("order_vendor_status")).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(orderVendorStatusList)) {
            //全部供应商订单为未发货==单据则为未发货
            if (!CollectionUtils.isEmpty(orderVendorStatusList) && orderVendorStatusList.stream().allMatch(t -> t.equals(OrderVendorStatusEnum.UpcomingDelivery.name()))) {
                orderCustomerStatus = OrderCustomerStatusEnum.UpcomingDelivery;
            }
            //只要有一个供应商订单为已发货==单据则为已发货
            if (!CollectionUtils.isEmpty(orderVendorStatusList) && orderVendorStatusList.stream().anyMatch(t -> t.equals(OrderVendorStatusEnum.DoneDelivery.name()))) {
                orderCustomerStatus = OrderCustomerStatusEnum.DoneDelivery;
            }
            //全部供应商订单为已关闭==单据则为已关闭
            if (!CollectionUtils.isEmpty(orderVendorStatusList) && orderVendorStatusList.stream().allMatch(t -> t.equals(OrderVendorStatusEnum.Closed.name()))) {
                orderCustomerStatus = OrderCustomerStatusEnum.Closed;
            }
            //全部商品为已完成或一个或多个商品已完成其余全都是已关闭==单据则为已完成
            if (!CollectionUtils.isEmpty(orderVendorStatusList) && orderVendorStatusList.stream().allMatch(t -> t.equals(OrderGoodsStatusEnum.Done.name()))) {
                orderCustomerStatus = OrderCustomerStatusEnum.Done;
            }
            List<String> orderCustomerStatusResult = orderVendorStatusList.stream().filter(t -> t.equals(OrderGoodsStatusEnum.Done.name())).collect(Collectors.toList());
            if (orderCustomerStatusResult.size() > 0 && orderCustomerStatusResult.size() == orderVendorStatusList.size()) {
                orderCustomerStatus = OrderCustomerStatusEnum.Done;
            }
            //客户订单状态修改
            for (String customerOrderId : customerOrderIds) {
                if (null != orderCustomerStatus) {
                    JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).putFieldAndVal("order_customer_status", orderCustomerStatus.name())
                            .eq("id", customerOrderId).update();
                }
            }
        }
        updateTransferOrderStatus(customerOrderIds);
        dockFinanceService.writeBackTradesOrder(writeBackParams);
    }

    /**
     * 修改转采订单状态
     */
    public void updateTransferOrderStatus(Collection<String> customerOrderIds) {
        if (CollectionUtils.isEmpty(customerOrderIds)) {
            return;
        }

        List<Map<String, Object>> orderCustomerGoodsList = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).selectField("*")
                .in("order_customer_id", customerOrderIds).queryForList();

        if (CollectionUtils.isEmpty(orderCustomerGoodsList)) {
            return;
        }
        orderCustomerGoodsList.forEach(orderCustomerGoods -> {
            //设置转采商品状态
            JdbcTemplateUtils.builder(AppConst.ZHUANCAI, ModelConst.T_TRANSFER_ORDER_GOODS).putFieldAndVal("transfer_order_goods_status", orderCustomerGoods.get("order_customer_goods_status"))
                    .eq("cloud_order_goods_id", orderCustomerGoods.get("id")).update();
        });
        List<Map<String, Object>> orderCustomers = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).selectField("*").in("id", customerOrderIds).queryForList();
        orderCustomers.forEach(orderCustomer -> {

            Map<String, Object> transferOrderParam = new HashMap<>();
            transferOrderParam.put("transfer_order_status", orderCustomer.get("order_customer_status"));

            // 对应老的 PAID 已付款 =》未接单 | 未发货 | 已发货
            List<String> orderCustomerStatusList = new ArrayList<>();
            orderCustomerStatusList.add(OrderCustomerStatusEnum.UpcomingConfirm.name());
            orderCustomerStatusList.add(OrderCustomerStatusEnum.UpcomingDelivery.name());
            orderCustomerStatusList.add(OrderCustomerStatusEnum.DoneDelivery.name());

            if (orderCustomerStatusList.contains(String.valueOf(orderCustomer.get("order_customer_status")))) {
                transferOrderParam.put("pay_time", new Date());
            }
            //设置转采订单状态
            JdbcTemplateUtils.builder(AppConst.ZHUANCAI, ModelConst.T_TRANSFER_ORDER).putFieldAndVal(transferOrderParam)
                    .eq("cloud_order_id", orderCustomer.get("id")).update();
        });
    }

    /**
     * 分批收货
     * cn/gomro/core/bizes/order/service/impl/OrdersService.goodsReceipt
     *
     * @param orderGoodsId
     * @param num
     * @return
     * @throws
     */
    @Override
    public Boolean goodsReceipt(String orderGoodsId, BigDecimal num) throws RuntimeException {

        if (null == num || num.compareTo(BigDecimal.ZERO) < 1 || null == orderGoodsId) {
            throw new RuntimeException("收货参数为空");
        }
        HashMap<String, OrderGoodsStatusEnum> map = new HashMap<>();
        Map<String, Object> orderGoodsCustomerParam = new HashMap<>();
        Map<String, Object> orderGoodsVendorParam = new HashMap<>();

        Map<String, Object> orderGoodsEntity = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS)
                .selectField("*").eq("id", orderGoodsId).queryForMap();

        //TODO 调用查询驻场工程师接口
        //可收货数
        BigDecimal enableNum = getEnableNum(orderGoodsId);
        Map<String, Object> orderVendorGoods = getOrderGoods(orderGoodsId, null);
        //可发货数
        BigDecimal deliverableNum = getDeliverableNum((String) orderVendorGoods.get("id"));
        if (enableNum.compareTo(num) == -1)
            throw new RuntimeException("收货数量不能大于" + BigDecimalUtils.round(enableNum, 2));
        if (num.compareTo(enableNum) ==0 && deliverableNum.compareTo(BigDecimal.ZERO) != 1) {
            orderGoodsCustomerParam.put("order_customer_goods_status", OrderGoodsStatusEnum.Done.name());
            orderGoodsVendorParam.put("order_vendor_goods_status", OrderGoodsStatusEnum.Done.name());
            map.put((String) orderGoodsEntity.get("id"), OrderGoodsStatusEnum.Done);
        }

        //收货前的时间
        orderGoodsCustomerParam.put("delivery_time", DateUtils.getCurrentDate());
        orderGoodsVendorParam.put("delivery_time", DateUtils.getCurrentDate());
        //已收货数量,原已收货数量+现收货数量
        BigDecimal quantityReceived = BigDecimalUtils.add(BigDecimalUtils.isNull(orderGoodsEntity.get("quantity_received")), num);
        orderGoodsCustomerParam.put("quantity_received", quantityReceived);
        orderGoodsVendorParam.put("quantity_received", quantityReceived);
        //更新客户订单商品表
        Integer i = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal(orderGoodsCustomerParam)
                .eq("id", orderGoodsId).update();
        //更新供应商订单商品表
        JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal(orderGoodsVendorParam)
                .eq("id", orderVendorGoods.get("id")).update();

        //存收货单 OrderGoodsReceivedEntity
        Map<String, Object> orderGoodsAccept = new HashMap<>();
        SelectorFormat acceptUserId = getSelectorFormat(null, UnitType.USER);
        orderGoodsAccept.put("order_customer_goods_id", orderGoodsId);
        orderGoodsAccept.put("order_vendor_goods_id", orderVendorGoods.get("id"));
        orderGoodsAccept.put("quantity", num);
        orderGoodsAccept.put("accept_user_id", acceptUserId);
        orderGoodsAccept.put("accept_user_fullname", acceptUserId.getName());
        SingleResponse<BO> createBo = BoServiceUtils.createBo(ModelConst.T_ORDER_GOODS_ACCEPT, Collections.singletonList(orderGoodsAccept));

        Map<String, Object> data = createBo.getData().getData();
        //1.	回写订单商品状态、供应商订单状态、客户订单状态，订单商品已收货数量、订单商品最后一次收货时间；调用转采服务回写订单商品状态；调用财务回写订单商品状态
        updateOrderStatus(Collections.singletonList((String) orderGoodsEntity.get("order_customer_id")));
        //2.	调用金蝶服务生成收货凭证
        OrderGoodsAcceptVO orderGoodsAcceptVO = OrderGoodsAcceptVO.entityToVO(data);
        List<Voucher> vouchers = orderCreateVoucher.receiveCreateVoucher(Collections.singletonList(orderGoodsAcceptVO));
        //3.	调用财务服务生成收货账单
        orderGoodsEntity.put("num", num);
        dockFinanceService.createBill(Collections.singletonList(orderGoodsEntity));
        return i > 0 ? true : false;
    }

    /**
     * 批量收货
     * cn/gomro/core/bizes/order/service/impl/OrdersService.goodsReceiptBatch
     *
     * @param orderCustomerGoodIds
     * @return
     * @throws RuntimeException
     */
    @Override
    public TempOrderReceiptVo goodsReceiptBatch(List<String> orderCustomerGoodIds) throws RuntimeException {
//        TODO 平台账户不允许操作

        List<Map<String, Object>> orderGoodsList = getOrderCustomerGoodsByGoodsId(orderCustomerGoodIds);

        if (null == orderGoodsList || orderGoodsList.isEmpty())
            throw new RuntimeException("商品信息不存在！");

        Boolean flag = true;

        List<Map<String, Object>> ogreList = new ArrayList<>();
        HashMap<String, OrderGoodsStatusEnum> map = new HashMap<>();
        TempOrderReceiptVo tempOrderReceiptVo = new TempOrderReceiptVo();

        Set<String> customerOrderIds = new HashSet<>();
        for (Map<String, Object> orderGoodsEntity : orderGoodsList) {
            //通过供应商商品ID获取客户商品信息
            Map<String, Object> orderVendorGoods = getOrderGoods((String) orderGoodsEntity.get("id"), null);

//            if (!RegexUtils.notNull((String) orderGoodsEntity.get("attachment"))) {
//                throw new RuntimeException("请先上传收货单！");
//            }

            //可收货数
            BigDecimal enableNum = this.getEnableNum((String) orderGoodsEntity.get("id"));
            if (enableNum.compareTo(BigDecimal.ZERO) != 1) {
                throw new RuntimeException("订单商品编号【" + orderGoodsEntity.get("id") + "】可收货数量【" + enableNum.toPlainString() + "】必须大于0");
            }
            if (orderGoodsEntity.get("order_customer_goods_status").equals(OrderGoodsStatusEnum.DoneDelivery.name())) {

                //用于同步交易记录商品状态
                map.put((String) orderGoodsEntity.get("id"), OrderGoodsStatusEnum.Done);

                //添加收货记录
                Map<String, Object> ogre = new HashMap<>();
                SelectorFormat acceptUserId = getSelectorFormat(null, UnitType.USER);
                ogre.put("order_customer_goods_id", orderGoodsEntity.get("id"));
                ogre.put("order_vendor_goods_id", getOrderGoods((String) orderGoodsEntity.get("id"), null).get("id"));
                ogre.put("quantity", BigDecimalUtils.round(enableNum, 6));
                ogre.put("accept_user_id", acceptUserId);
                ogre.put("accept_user_fullname", acceptUserId.getName());
                //VMI商品在创建订单即收货完成
                if (orderGoodsEntity.get("goods_src").equals(GoodsSrcEnum.Vmi.name())) {
                    ogre.put("quantity", orderGoodsEntity.get("num"));
                }
                //更新客户订单商品和供应商订单商品状态和收货时间
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal("delivery_time", new Date())
                        .putFieldAndVal("quantity_received", BigDecimalUtils.round(BigDecimalUtils.isNull(orderGoodsEntity.get("quantity")), 6))
                        .putFieldAndVal("order_customer_goods_status", OrderGoodsStatusEnum.Done.name()).eq("id", orderGoodsEntity.get("id")).update();
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal("delivery_time", new Date())
                        .putFieldAndVal("quantity_received", BigDecimalUtils.round(BigDecimalUtils.isNull(orderGoodsEntity.get("quantity")), 6))
                        .putFieldAndVal("order_vendor_goods_status", OrderGoodsStatusEnum.Done.name()).eq("id", orderVendorGoods.get("id")).update();

                orderGoodsEntity.put("num", enableNum);
                customerOrderIds.add((String) orderGoodsEntity.get("order_customer_id"));
                ogreList.add(ogre);
                flag = false;
            }
        }
        //调用财务回写订单商品状态、调用转采服务回写订单商品状态
        updateOrderStatus(new ArrayList<>(customerOrderIds));
        List<Map<String, Object>> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(ogreList)) {
            //获取 订单商品收货表 创建之后的数据
            for (Map<String, Object> ogre : ogreList) {
                SingleResponse<BO> bo = BoServiceUtils.createBo(ModelConst.T_ORDER_GOODS_ACCEPT, Collections.singletonList(ogre));
                Assert.isTrue(bo != null, "写入 订单商品收货表数据 失败 ！！！");
                list.add(bo.getData().getData());
                tempOrderReceiptVo.setReceivedIds(Collections.singletonList(bo.getData().getBizObjectId()));
            }
        }

        if (flag) throw new RuntimeException("无已发货商品，批量收货失败！");
        //调用金蝶服务生成收货凭证
        Assert.isTrue(list != null && list.size() > 0, "没有订单商品收货数据，无法生成金蝶凭证 数据 ！！！");
        List<OrderGoodsAcceptVO> orderGoodsAcceptVOList = list.stream().map(e -> OrderGoodsAcceptVO.entityToVO(e)).collect(Collectors.toList());

        // todo 對外接口需要用到
        List<Voucher> vouchers = orderCreateVoucher.receiveCreateVoucher(orderGoodsAcceptVOList);
        //调用财务服务生成收货账单
        dockFinanceService.createBill(orderGoodsList);

        tempOrderReceiptVo.setOrderGoodsList(orderGoodsList);
        return tempOrderReceiptVo;
    }

    /**
     * 客户申请退款
     *
     * @return
     * @throws RuntimeException
     */
    @Override
    public List<Map<String, Object>> applyRefund(List<BulkRefundVO> bulkRefundVO) throws RuntimeException {
        List<Map<String, Object>> orderCustomerGoodsList = getOrderCustomerGoodsByGoodsId(bulkRefundVO.stream().map(BulkRefundVO::getOrderGoodsId).collect(Collectors.toList()));
        Set<OrderGoodsStatusEnum> status = orderCustomerGoodsList.stream().map(e -> OrderGoodsStatusEnum.valueOf((String) e.get("order_customer_goods_status"))).collect(Collectors.toSet());
        //只支持供应商未发货退款和客户已收货退款，且只能单种操作
        if (status.size() > 1) {
            throw new RuntimeException("退款只支持相同订单商品状态批量退款");
        }
        List<Map<String, Object>> results = new ArrayList<>();
        for (BulkRefundVO refundVO : bulkRefundVO) {
            String orderGoodsId = refundVO.getOrderGoodsId();
            BigDecimal num = refundVO.getNum();
            BigDecimal amount = refundVO.getAmount();
            String memo = refundVO.getMemo();

            if (null == amount || null == num || null == memo)
                throw new RuntimeException("申请退款信息不完整！");
            if (num.compareTo(BigDecimal.ZERO) != 1) throw new RuntimeException("退款数量不能小于0！");
            if (amount.compareTo(BigDecimal.ZERO) < 1) throw new RuntimeException("金额不能小于等于0！");

            Map<String, Object> orderGoods = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS)
                    .selectField("*").eq("id", orderGoodsId).queryForMap();

            if (null == orderGoods) throw new RuntimeException("订单商品不存在！");

            //未发货数量
            BigDecimal undeliveredNum = getUndeliveredNum(orderGoodsId);

            //申请退款，如果既有发货也有未发的，提供给客户两个选择，申请已发的还是未发的，申请并售后完成后，再次申请另外一个
            /*if (undeliveredNum.compareTo(BigDecimal.ZERO)==1&&BigDecimalUtils.isNull(orderGoods.get("quantity_received")).compareTo(BigDecimal.ZERO)==1) {
                if(BigDecimalUtils.isNull(orderGoods.get("quantity_received")).compareTo(num)!=0){
                    throw new RuntimeException("已有收货数量，请优先退收货数量,退货数量与收货数量保持一致！");
                }
            }*/

            //可退数量
            BigDecimal refundableNum = getRefundableNum(orderGoodsId);

            //已发数量
//            BigDecimal deliveredNum = getDeliveredNum(orderGoodsId, null);

            Map<String, Object> vo = selectModelById((String) orderGoods.get("order_vendor_id"), ModelConst.T_ORDER_VENDOR);

            Map<String, Object> co = selectModelById((String) orderGoods.get("order_customer_id"), ModelConst.T_ORDER_CUSTOMER);

            if (null == vo || null == co) throw new RuntimeException("订单不存在！");

            if (refundableNum.compareTo(num) == -1) throw new RuntimeException("申请退款数量不能大于可退数量！");

            //一个订单商品只能存在一个正在进行中的退货记录
            List<Map<String, Object>> orderGoodsReturns = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURNS).selectField("*").eq("order_customer_goods_id", orderGoods.get("id"))
                    .in("order_goods_returns_status", OrderGoodsReturnsStatusEnum.getProgressStatus()).queryForList();
            if (!CollectionUtils.isEmpty(orderGoodsReturns))
                throw new RuntimeException("一个订单商品只能存在一个正在进行中的退货记录！");

            BigDecimal calAmount = BigDecimalUtils.round(BigDecimalUtils.mul(num, BigDecimalUtils.isNull(orderGoods.get("price"))), 2);

            //添加退货申请记录
            List<Map<String, Object>> orderGoodsRefunds = new ArrayList<>();
            Map<String, Object> orderGoodsRefund = new HashMap<>();
            Map<String, Object> orderVendorGoods = getOrderGoods((String) orderGoods.get("id"), null);
            //如果该商品属于部分发货时，需要区分退已发和未发的，并且优先退已发货的，会生成两条退货记录，一条是已发货的(is_returns=true)，一条是未发货的(is_returns=false)
            orderGoodsRefund.put("order_customer_id", orderGoods.get("order_customer_id"));
            orderGoodsRefund.put("order_customer_goods_id", orderGoods.get("id"));
            orderGoodsRefund.put("order_vendor_id", orderGoods.get("order_vendor_id"));
            orderGoodsRefund.put("order_vendor_goods_id", orderVendorGoods.get("id"));
            orderGoodsRefund.put("old_status", orderGoods.get("order_customer_goods_status"));
            orderGoodsRefund.put("quantity", BigDecimalUtils.round(num, 6));
            orderGoodsRefund.put("customer_amount", calAmount);
            orderGoodsRefund.put("vendor_amount", calAmount);
            orderGoodsRefund.put("is_to_pm", false);
            orderGoodsRefund.put("is_returns", false);
            orderGoodsRefund.put("memo", memo);
//            SingleResponse<BOList> response = BoServiceUtils.findListBySimple(ModelConst.T_MEMBER_BANK_ACCOUNT, "member_id", getSelectorFormat(null, UnitType.USER));
            SessionUser sessionUser = new SessionUser();
            Assert.notNull(sessionUser.get(),"未获取到用户信息！！！");
            List<Map<String, Object>> mapList = JdbcTemplateUtils.builder(AppConst.PERSONAL_CENTER,ModelConst.T_MEMBER_BANK_ACCOUNT).selectField("*").eq("member_id -> '$.id'", sessionUser.getCurrentUserId()).queryForList();
            if (!CollectionUtils.isEmpty(mapList)) {
                Map<String, Object> mba = mapList.get(0);
                orderGoodsRefund.put("bank_info", ObjectUtil.defaultIfNull(mba.get("bank_info"), ""));
                orderGoodsRefund.put("bank_no", ObjectUtil.defaultIfNull(mba.get("bank_no"), ""));
                orderGoodsRefund.put("bank_account", ObjectUtil.defaultIfNull(mba.get("bank_account"), ""));
                orderGoodsRefund.put("phone", ObjectUtil.defaultIfNull(mba.get("phone"), ""));
                orderGoodsRefund.put("address", ObjectUtil.defaultIfNull(mba.get("address"), ""));
            }
            orderGoodsRefund.put("receiver", co.get("receiver"));
            orderGoodsRefund.put("mobile", co.get("phone"));
            orderGoodsRefund.put("customer_member_id", Objects.isNull(co.get("place_order_user_id")) ? null : JSON.parseObject((String) co.get("place_order_user_id"), SelectorFormat.class));
            orderGoodsRefund.put("customer_member_name", co.get("place_order_fullname"));
            orderGoodsRefund.put("customer_organization_id", Objects.isNull(co.get("organization_id")) ? null : JSON.parseObject((String) co.get("organization_id"), SelectorFormat.class));
            orderGoodsRefund.put("customer_organization_name", co.get("organization_name"));
            orderGoodsRefund.put("vendor_organization_id", Objects.isNull(vo.get("organization_id")) ? null : JSON.parseObject((String) vo.get("organization_id"), SelectorFormat.class));
            orderGoodsRefund.put("vendor_organization_name", vo.get("organization_name"));
            orderGoodsRefund.put("origin_status", null);
            orderGoodsRefund.put("origin_old_status", null);
            orderGoodsRefund.put("transfer_refund_confirm", null);
            orderGoodsRefund.put("order_goods_returns_status", OrderGoodsReturnsStatusEnum.PendingMiddlemanConfirm.name());
            //把当前退款时间、退款人、退款备注、退款抬头保存到扩展字段中
            //解析logs
            Map<String, Object> extendsAttr = new HashMap<>();
            List<Map<String, Object>> logs = new ArrayList<>();
            Map<String, Object> log = new HashMap<>();
            log.put("operator", RequestContext.getLoginRealName());
            log.put("operatorUserId", RequestContext.getLoginId());
            log.put("behavior", BehaviorEnum.APPLY_REFUND.getText());
            log.put("architectureName", organizationFeignService.listLabelByUserId(RequestContext.getCorpLoginId()).getData().get(0).getName());
            log.put("memo", memo);
            log.put("time", DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
            logs.add(log);
            extendsAttr.put("logs", logs);
            orderGoodsRefund.put("extends_attr", JSON.toJSONString(extendsAttr));
            //如果已发货数量大于0，则需要退货
            if (BigDecimalUtils.isNull(orderGoods.get("quantity_shipped")).compareTo(BigDecimal.ZERO) == 1) {
                orderGoodsRefund.put("is_returns", true);
            }
            orderGoodsRefund.put("platform_id", StrUtil.isEmptyIfStr(co.get("platform_id")) ? null : JsonParseObject.parseObject((String) co.get("platform_id"), SelectorFormat.class).get(0));
            orderGoodsRefunds.add(orderGoodsRefund);
            //回写订单客户订单商品已退未发数量和已退已发货数量
            if (orderGoods.get("order_customer_goods_status").equals(OrderGoodsStatusEnum.DoneDelivery.name()) || orderGoods.get("order_customer_goods_status").equals(OrderGoodsStatusEnum.Done.name())) {
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal("quantity_return_shipped", BigDecimalUtils.add(orderGoods.get("quantity_return_shipped"), num))
                        .putFieldAndVal("returned_num", BigDecimalUtils.add(orderGoods.get("quantity_return_shipped"), num)).eq("id", orderGoods.get("id")).update();
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal("quantity_return_shipped", BigDecimalUtils.add(orderGoods.get("quantity_return_shipped"), num))
                        .putFieldAndVal("returned_num", BigDecimalUtils.add(orderGoods.get("quantity_return_shipped"), num)).eq("id", orderVendorGoods.get("id")).update();
            } else {
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal("quantity_return_not_shipped", BigDecimalUtils.add(orderGoods.get("quantity_return_not_shipped"), num))
                        .eq("id", orderGoods.get("id")).update();
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal("quantity_return_not_shipped", BigDecimalUtils.add(orderGoods.get("quantity_return_not_shipped"), num))
                        .eq("id", orderVendorGoods.get("id")).update();
            }
            //客户申请退款（供应商已发货）       -》label改为：退款申请中（平台审批中）
            this.editOrderLabel(StrUtil.str(orderGoods.get("id"), Charset.defaultCharset()),
                    StrUtil.str(orderVendorGoods.get("id"), Charset.defaultCharset()),OrderApproveStatusEnum.REFUND_APPLICATION);
            //回写客户、供应商订单,售后情况
            JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).putFieldAndVal("after_sale", "售后中").eq("id", orderGoods.get("order_customer_id")).update();
            JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR).putFieldAndVal("after_sale", "售后中").eq("id", orderGoods.get("order_vendor_id")).update();

            updateTransferOrderStatus(Collections.singletonList((String) orderGoods.get("order_customer_id")));

            SingleResponse<BO> save = BoServiceUtils.createBo(ModelConst.T_ORDER_GOODS_RETURNS, orderGoodsRefunds);
            if (null == save) throw new RuntimeException("退款申请失败！");

            results.add(save.getData().getData());
            //TODO 巴德富申请退款需要提醒
            //回写退货账单
            dockFinanceService.refundBill(orderGoodsRefunds);
        }
        return results;
    }

    /**
     * 根据客户订单商品ID查询供应商订单商品或供应商订单商品ID查询客户订单商品
     *
     * @param orderCustomerGoodsId
     * @param orderVendorGoodsId
     * @return
     */
    @Override
    public Map<String, Object> getOrderGoods(String orderCustomerGoodsId, String orderVendorGoodsId) {
        String sql = "";
        if (StringUtils.isNotBlank(orderCustomerGoodsId)) {
            sql = "select cg.* from " + getTableName(ModelConst.T_ORDER_VENDOR_GOODS) + " cg\n" +
                    "INNER JOIN " + getTableName(ModelConst.T_ORDER_CUSTOMER_GOODS) + " vg on cg.order_customer_id = vg.order_customer_id\n" +
                    "and cg.order_vendor_id = vg.order_vendor_id and cg.goods_id = vg.goods_id\n" +
                    "where vg.id='" + orderCustomerGoodsId + "'";
        }
        if (StringUtils.isNotBlank(orderVendorGoodsId)) {
            sql = "select vg.* from " + getTableName(ModelConst.T_ORDER_VENDOR_GOODS) + " cg\n" +
                    "INNER JOIN " + getTableName(ModelConst.T_ORDER_CUSTOMER_GOODS) + " vg on cg.order_customer_id = vg.order_customer_id\n" +
                    "and cg.order_vendor_id = vg.order_vendor_id and cg.goods_id = vg.goods_id\n" +
                    "where cg.id='" + orderVendorGoodsId + "'";
        }
        List<Map<String, Object>> orderGoods = JdbcTemplateUtils.queryForList(sql, new HashMap<>());
        return !CollectionUtils.isEmpty(orderGoods) ? orderGoods.get(0) : null;
    }

    /**
     * 审批退款申请
     * cn/gomro/core/bizes/order/service/impl/OrdersService.approvalRefund
     *
     * @param agreeRefundVO
     * @return
     */
    @Override
    public SingleResponse approvalRefund(AgreeRefundVO agreeRefundVO) {
        if (null == agreeRefundVO || null == agreeRefundVO.getOrderGoodsIds() || agreeRefundVO.getOrderGoodsIds().isEmpty())
            throw new RuntimeException("退款信息不完整！");

        List<Map<String, Object>> existOrderVendorGoods = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).selectField("*")
                .in("id", agreeRefundVO.getOrderGoodsIds()).queryForList();

        if (CollectionUtils.isEmpty(existOrderVendorGoods)) throw new RuntimeException("订单商品信息不存在！");

        List<Map<String, Object>> orderGoodsReturns = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURNS)
                .selectField("*").in("order_vendor_goods_id", agreeRefundVO.getOrderGoodsIds())
                .in("order_goods_returns_status", OrderGoodsReturnsStatusEnum.getProgressStatus()).queryForList();

        if (CollectionUtils.isEmpty(orderGoodsReturns)) throw new RuntimeException("退款信息不存在！");

        List<Map<String, Object>> ogrParams = new ArrayList<>();
        List<String> orderCustomerIds = new ArrayList<>();

        for (Map<String, Object> ogre : orderGoodsReturns) {
            Map<String, Object> ogrParam = new HashMap<>();
            ogrParam.put("id", ogre.get("id"));
            //解析logs
            Map<String, Object> extendsAttr = Objects.isNull(ogre.get("extends_attr")) ? null : JSON.parseObject((String) ogre.get("extends_attr"), HashMap.class);
            List<Map<String, Object>> logs = new ArrayList<>();
            if (!CollectionUtils.isEmpty(extendsAttr)) {
                logs = JSON.parseObject(JSON.toJSONString(extendsAttr.get("logs")), ArrayList.class);
            } else {
                extendsAttr = new HashMap<>();
            }
            Map<String, Object> log = new HashMap<>();
            String behavior = "";
            String orderCustomerGoodsId = StrUtil.str(ogre.get("order_customer_goods_id"), Charset.defaultCharset());
            String orderVendorGoodsId = StrUtil.str(ogre.get("order_vendor_goods_id"), Charset.defaultCharset());
            Map<String, Object> orderVendor = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR).selectField("*").eq("id", ogre.get("order_vendor_id")).queryForMap();
            //  默认/true 同意退款申请
            if (null == agreeRefundVO.getApproval() || agreeRefundVO.getApproval()) {
                //判断是平台审批还是供应商审批
                if (null != agreeRefundVO.getType() && agreeRefundVO.getType().equals("1")) {
                    //如果供应商为虚拟供应商是修改退货记录为待财务确认，否则修改退货记录为待供应商审批
                    if (isVirtual(Objects.isNull(orderVendor.get("organization_id")) ? null : JSON.parseObject((String) orderVendor.get("organization_id"), SelectorFormat.class))) {
                        ogrParam.put("order_goods_returns_status", OrderGoodsReturnsStatusEnum.PendingFinanceConfirm.name());
                    } else {
                        ogrParam.put("order_goods_returns_status", OrderGoodsReturnsStatusEnum.PendingVendorConfirm.name());
                    }
                    //据页面选择退平台还是退供应商去修改退货记录is_to_pm字段，如果退平台is_to_pm=true
                    String isToPm = null;
                    if (null != agreeRefundVO.getRefundRole()) {
                        isToPm = agreeRefundVO.getRefundRole() ? "0" : "1";
                    } else {
                        isToPm = StrUtil.utf8Str(ogre.get("is_to_pm"));
                    }
                    //平台审批 -> 仅退款
                    if (!Utils.parseObjToBool(ogre.get("is_returns"))) {
                        //平台审批（无退货） ->同意退款 ->label改为：退款中（供应商审批中）
                        this.editOrderLabel(orderCustomerGoodsId,orderVendorGoodsId,OrderApproveStatusEnum.REFUNDING);
                    }else{
                        //平台审批（退供应商）
                        if (null != agreeRefundVO.getRefundRole() && agreeRefundVO.getRefundRole()){
                            //平台审批（退供应商） ->同意退款 ->label改为：退货中（供应商审批中）
                            this.editOrderLabel(orderCustomerGoodsId,orderVendorGoodsId,OrderApproveStatusEnum.RETURNING);
                        //平台审批（退平台）
                        }else if(null != agreeRefundVO.getRefundRole() && !agreeRefundVO.getRefundRole()){
                            //平台审批（退平台） ->同意退款 ->label改为：待退货（客户退货）
                            this.editOrderLabel(orderCustomerGoodsId,orderVendorGoodsId,OrderApproveStatusEnum.TO_RETURN);
                        }
                    }
                    ogrParam.put("is_to_pm", isToPm);
                    behavior = BehaviorEnum.AGREE_REFUND.getText();
                } else if (agreeRefundVO.getType().equals("2")) {
                    //如果仅退款，修改状态为已完成
                    if (!Utils.parseObjToBool(ogre.get("is_returns"))) {
                        ogrParam.put("order_goods_returns_status", OrderGoodsReturnsStatusEnum.Done.name());
                        //TODO 调用财务生成退款账单数据和修改账户信用额度
                        //修改退款、退货用户售后情况
                        updateAfterSale(ogre);
                        behavior = BehaviorEnum.AGREE_REFUND.getText();
                        //供应商审批（仅退款） ->同意退款 ->label置空
                        this.editOrderLabel(orderCustomerGoodsId,orderVendorGoodsId,null);
                    } else {
                        //需要退货, 修改退货记录状态为未退货
                        ogrParam.put("order_goods_returns_status", OrderGoodsReturnsStatusEnum.ReturnPending.name());
                        behavior = BehaviorEnum.RETURN.getText();
                    }
                }

            } else {
                //判断是平台审批还是供应商审批
                if (null != agreeRefundVO.getType() && agreeRefundVO.getType().equals("2")) {
                    //修改退货记录状态为审批中
                    ogrParam.put("order_goods_returns_status", OrderGoodsReturnsStatusEnum.PendingMiddlemanConfirm.name());
                    //供应商审批(拒绝退款)	     》label改为：退款申请中（平台审批中）
                    this.editOrderLabel(orderCustomerGoodsId,orderVendorGoodsId,OrderApproveStatusEnum.REFUND_APPLICATION);
                } else if (agreeRefundVO.getType().equals("3") || agreeRefundVO.getType().equals("1")) {
                    //修改退货记录状态为已关闭
                    ogrParam.put("order_goods_returns_status", OrderGoodsReturnsStatusEnum.Closed.name());
                    //售后取消，需要回写客户订单、供应商订单的售后情况，客户和供应商订单商品已退数量
                    //退货，则为已退已发数量
                    Map<String, Object> orderVendorGoods = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).selectField("*").eq("id", orderVendorGoodsId).queryForMap();
                    if (Utils.parseObjToBool(ogre.get("is_returns"))) {
                        BigDecimal vendor_quantity_return_not_shipped = BigDecimalUtils.sub(orderVendorGoods.get("quantity_return_shipped"), ogre.get("quantity"));
                        BigDecimal customer_quantity_return_not_shipped = BigDecimalUtils.sub(orderVendorGoods.get("quantity_return_shipped"), ogre.get("quantity"));
                        JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal("quantity_return_shipped", customer_quantity_return_not_shipped).eq("id", orderCustomerGoodsId).update();
                        JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal("quantity_return_shipped", vendor_quantity_return_not_shipped).eq("id", orderVendorGoodsId).update();
                    } else {
                        //退款，则更新已退未发数量
                        BigDecimal vendor_quantity_return_shipped = BigDecimalUtils.sub(orderVendorGoods.get("quantity_return_not_shipped"), ogre.get("quantity"));
                        BigDecimal customer_quantity_return_shipped = BigDecimalUtils.sub(orderVendorGoods.get("quantity_return_not_shipped"), ogre.get("quantity"));
                        JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal("quantity_return_not_shipped", customer_quantity_return_shipped).eq("id", orderCustomerGoodsId).update();
                        JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal("quantity_return_not_shipped", vendor_quantity_return_shipped).eq("id", orderVendorGoodsId).update();
                    }
                    //查询退货订单是否还存在进行中退货商品，如果不存在，修改订单售后情况为“未售后”
                    List<Map<String, Object>> customerReturns = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURNS)
                            .selectField("*").in("order_goods_returns_status", OrderGoodsReturnsStatusEnum.getProgressStatus()).eq("order_customer_id", ogre.get("order_customer_id")).queryForList();
                    if (CollectionUtils.isEmpty(customerReturns)) {
                        JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).putFieldAndVal("after_sale", "未售后").eq("id", ogre.get("order_customer_id")).update();
                    }

                    List<Map<String, Object>> vendorReturns = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURNS)
                            .selectField("*").in("order_goods_returns_status", OrderGoodsReturnsStatusEnum.getProgressStatus()).eq("order_vendor_id", ogre.get("order_vendor_id")).queryForList();
                    if (CollectionUtils.isEmpty(vendorReturns)) {
                        JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR).putFieldAndVal("after_sale", "未售后").eq("id", ogre.get("order_vendor_id")).update();
                    }
                    updateTransferOrderStatus(Collections.singletonList((String) ogre.get("order_customer_id")));
                    //平台审批 ->拒绝退款 ->label置空
                    //取消退款 ->label置空
                    this.editOrderLabel(orderCustomerGoodsId,orderVendorGoodsId,null);
                }
                behavior = BehaviorEnum.REFUSE_REFUND.getText();
            }
            //退货记录中的扩展字段的售后过程增加一条记录
            log.put("operator", RequestContext.getLoginRealName());
            log.put("operatorUserId", RequestContext.getLoginId());
            log.put("behavior", behavior);
            log.put("architectureName", organizationFeignService.listLabelByUserId(RequestContext.getCorpLoginId()).getData().get(0).getName());
            log.put("memo", agreeRefundVO.getComment());
            log.put("time", DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
            logs.add(log);
            extendsAttr.put("logs", logs);
            ogrParam.put("extends_attr", JSON.toJSONString(extendsAttr));
            if (!Objects.isNull(ogrParam.get("is_to_pm"))) {
                ogrParam.put("is_to_pm", ogrParam.get("is_to_pm").equals("1") ? true : false);
            }
            if (!Objects.isNull(ogrParam.get("is_returns"))) {
                ogrParam.put("is_returns", ogrParam.get("is_returns").equals("1") ? true : false);
            }
            ogrParams.add(ogrParam);
            orderCustomerIds.add((String) ogre.get("order_customer_id"));
        }
        SingleResponse bo = BoServiceUtils.updateMainBo(ModelConst.T_ORDER_GOODS_RETURNS, ogrParams);
//        updateOrderStatus(orderCustomerIds);
        return bo;
    }

    /**
     * 财务确认收供应商退款
     * cn/gomro/core/bizes/order/service/impl/OrdersService.refundFinanceConfirm
     *
     * @param orderGoodsReturnsIds 订单商品ID
     */
    public boolean refundFinanceConfirm(List<String> orderGoodsReturnsIds) {
        if (CollectionUtils.isEmpty(orderGoodsReturnsIds)) throw new RuntimeException("参数不能为空");

        List<Map<String, Object>> orderGoodsReturns = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURNS)
                .selectField("*").in("id", orderGoodsReturnsIds).queryForList();

        if (CollectionUtils.isEmpty(orderGoodsReturns)) throw new RuntimeException("商品退货表信息不存在");

        for (Map<String, Object> ogre : orderGoodsReturns) {
            // 修改退货记录状态为待供应商审批
            // 退货记录中的扩展字段售后记录增加一条
            Map<String, Object> extendsAttr = Objects.isNull(ogre.get("extends_attr")) ? null : JSON.parseObject((String) ogre.get("extends_attr"), HashMap.class);
            List<Map<String, Object>> logs = new ArrayList<>();
            Map<String, Object> log = new HashMap<>();
            if (!CollectionUtils.isEmpty(extendsAttr)) {
                logs = JSON.parseObject(JSON.toJSONString(extendsAttr.get("logs")), ArrayList.class);
            } else {
                extendsAttr = new HashMap<>();
            }
            //退货记录中的扩展字段的售后过程增加一条记录
            log.put("operator", RequestContext.getLoginRealName());
            log.put("operatorUserId", RequestContext.getLoginId());
            log.put("behavior", BehaviorEnum.FINANCE_CONFIRMED.getText());
            log.put("architectureName", organizationFeignService.listLabelByUserId(RequestContext.getCorpLoginId()).getData().get(0).getName());
            log.put("memo", "财务确认供应商退款");
            log.put("time", DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
            logs.add(log);
            extendsAttr.put("logs", logs);
            JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURNS).putFieldAndVal("order_goods_returns_status", OrderGoodsReturnsStatusEnum.PendingVendorConfirm.name())
                    .putFieldAndVal("extends_attr", JSON.toJSONString(extendsAttr)).eq("id", ogre.get("id")).update();
            //修改供应商订单售后情况为"售后中"
            JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR).putFieldAndVal("after_sale", "售后中").eq("id", ogre.get("order_vendor_id")).update();
        }
        return true;
    }

    /**
     * 确认到货
     * cn/gomro/core/bizes/order/service/impl/OrdersService.confireReturn
     *
     * @param orderVendorGoodsIds 供应商订单商品ID
     * @return
     */
    @Override
    public SingleResponse<BO> confireReturn(List<String> orderVendorGoodsIds) {

        List<Map<String, Object>> results = new ArrayList<>();

        if (null == orderVendorGoodsIds || orderVendorGoodsIds.isEmpty())
            throw new RuntimeException("退货商品不存在！");

        //退货、退款商品集合
        List<Map<String, Object>> ogreList = getGoodsReturnsByOrderGoodsId(null, orderVendorGoodsIds);

        if (null == ogreList || ogreList.isEmpty()) throw new RuntimeException("未获取到退款申请单，请联系管理员！");

        //获取可操作确认入库的退款单,必须为已发退货的退货记录
        Set<Map<String, Object>> collect = ogreList.stream().filter(t ->
                t.get("order_goods_returns_status").equals(OrderGoodsReturnsStatusEnum.ReturnedDoneDelivery.name())
        ).collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(collect)) throw new RuntimeException("未查询到已发退货的退货记录！");

        boolean toPm = false;
        List<String> customerOrderIds = new ArrayList<>();
        List<Map<String, Object>> customerOrderList = new ArrayList<>();
        for (Map<String, Object> ogre : collect) {
            Map<String, Object> ogreParam = new HashMap<>();
            Map<String, Object> custmerOrder = new HashMap<>();
            ogreParam.put("id", ogre.get("id"));
            custmerOrder.put("id", ogre.get("order_customer_goods_id"));
            Map<String, Object> orderVendorGoods = selectModelById((String) ogre.get("order_vendor_goods_id"), ModelConst.T_ORDER_VENDOR_GOODS);

            //此次成功退货数量
            BigDecimal num = BigDecimalUtils.isNull(ogre.get("quantity"));

            //退款单完成
            ogreParam.put("order_goods_returns_status", OrderGoodsReturnsStatusEnum.Done.name());

//            BigDecimal refundableNum = getRefundableNum(null, (String) orderVendorGoods.get("id"), BigDecimalUtils.isNull(orderVendorGoods.get("quantity")));
            BigDecimal receivedNum = getReceivedNum(null, (String) orderVendorGoods.get("id"));

            //记录退货的数量
            orderVendorGoods.put("returned_num", BigDecimalUtils.add(orderVendorGoods.get("returned_num"), num));
//            custmerOrder.put("returned_num",orderVendorGoods.get("returned_num"));

            //记录退的收货部分的数量
            //若退货前，收货数量大于0
            BigDecimal returnReceiveNum;
            BigDecimal returnPmReceiveNum = BigDecimal.ZERO;
            if (receivedNum.compareTo(BigDecimal.ZERO) == 1) {
                //当次退的数量跟（收货数量-已退收货数量）比较
                BigDecimal returnReceivedNum = BigDecimalUtils.isNull(orderVendorGoods.get("return_received_num"));
                BigDecimal returnPmReceivedNum = BigDecimalUtils.isNull(orderVendorGoods.get("return_pm_received_num"));
                if (num.compareTo(BigDecimalUtils.sub(receivedNum, returnReceivedNum)) == 1) {
                    //大于已退收货数量更新为收货数量
                    returnReceiveNum = receivedNum;
                    if (toPm) {
                        returnPmReceiveNum = BigDecimalUtils.add(returnPmReceivedNum, BigDecimalUtils.sub(receivedNum, returnReceivedNum));
                    }
                } else {
                    //小于则累加退货数量
                    returnReceiveNum = BigDecimalUtils.add(num, returnReceivedNum);
                    if (toPm) {
                        returnPmReceiveNum = BigDecimalUtils.add(num, returnPmReceivedNum);
                    }
                }
                orderVendorGoods.put("return_received_num", returnReceiveNum);
                custmerOrder.put("return_received_num", orderVendorGoods.get("return_received_num"));
                if (toPm) {
                    orderVendorGoods.put("return_pm_received_num", returnPmReceiveNum);
                    custmerOrder.put("return_pm_received_num", orderVendorGoods.get("return_pm_received_num"));
                }
            }

            //修改订单状态
            customerOrderIds.add((String) orderVendorGoods.get("customer_order_id"));

            if (toPm) {

                BigDecimal returnedPM = BigDecimal.ZERO;

                List<Map<String, Object>> orderGoodsReturnStorageList = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURN_STORAGE).selectField(" * ").eq("order_goods_id", orderVendorGoods.get("id"))
                        .queryForList();
                //总退平台的数量
                if (null != orderGoodsReturnStorageList && !orderGoodsReturnStorageList.isEmpty()) {
                    for (Map<String, Object> ogres : orderGoodsReturnStorageList) {
                        returnedPM = BigDecimalUtils.add(BigDecimalUtils.isNull(ogres.get("num")), returnedPM);
                    }
                }
            }

            // 退货记录中的扩展字段售后记录增加一条
            Map<String, Object> extendsAttr = Objects.isNull(ogre.get("extends_attr")) ? null : JSON.parseObject((String) ogre.get("extends_attr"), HashMap.class);
            List<Map<String, Object>> logs = new ArrayList<>();
            Map<String, Object> log = new HashMap<>();
            if (!CollectionUtils.isEmpty(extendsAttr)) {
                logs = JSON.parseObject(JSON.toJSONString(extendsAttr.get("logs")), ArrayList.class);
            } else {
                extendsAttr = new HashMap<>();
            }
            //退货记录中的扩展字段的售后过程增加一条记录
            log.put("operator", RequestContext.getLoginRealName());
            log.put("operatorUserId", RequestContext.getLoginId());
            log.put("behavior", BehaviorEnum.CONFIRM_RECEIVED.getText());
            log.put("architectureName", organizationFeignService.listLabelByUserId(RequestContext.getCorpLoginId()).getData().get(0).getName());
            log.put("memo", "供应商确认到货");
            log.put("time", DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
            logs.add(log);
            extendsAttr.put("logs", logs);
            ogreParam.put("extends_attr", JSON.toJSONString(extendsAttr));

            //修改退款、退货用户售后情况
            updateAfterSale(ogre);

            try {
                // 调用退货凭证
                OrderGoodsReturnsVO orderGoodsReturnsVO = OrderGoodsReturnsVO.entityToVO(ogre);
                orderCreateVoucher.returnCreateVoucher(orderGoodsReturnsVO, toPm);
            } catch (Exception e) {
                e.printStackTrace();
            }
            results.add(ogreParam);
            customerOrderList.add(custmerOrder);
            //确认到货（供应商）      -》label置空
            //待确认入库（平台）      -》label置空
            this.editOrderLabel(StrUtil.str(ogre.get("order_customer_goods_id"), Charset.defaultCharset()),
                    StrUtil.str(ogre.get("order_vendor_goods_id"), Charset.defaultCharset()),null);
        }
        //修改订单状态，并回写交易记录商品状态
        updateOrderStatus(customerOrderIds);
        BoServiceUtils.updateMainBo(ModelConst.T_ORDER_CUSTOMER_GOODS, customerOrderList);
        return BoServiceUtils.updateMainBo(ModelConst.T_ORDER_GOODS_RETURNS, results);
    }

    /**
     * 修改退款、退货用户售后情况
     *
     * @param ogre
     * @return
     */
    private void updateAfterSale(Map<String, Object> ogre) {
        if (CollectionUtils.isEmpty(ogre)) {
            return;
        }
        //调用修改客户订单、供应商订单售后情况
        JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR).putFieldAndVal("after_sale", "已售后").eq("id", ogre.get("order_vendor_id")).update();
        JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).putFieldAndVal("after_sale", "已售后").eq("id", ogre.get("order_customer_id")).update();
        BigDecimal refundableNum = this.getRefundableNum((String) ogre.get("order_customer_goods_id"));
        //可退货数量==0，则修改为订单商品状态为已取消
        if (refundableNum.compareTo(BigDecimal.ZERO) == 0) {
            JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal("order_customer_goods_status", OrderGoodsStatusEnum.Closed.name()).eq("id", ogre.get("order_customer_goods_id")).update();
            JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal("order_vendor_goods_status", OrderGoodsStatusEnum.Closed.name()).eq("id", ogre.get("order_vendor_goods_id")).update();
            List<Map<String, Object>> orderVendorGoodsNew = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS)
                    .selectField("*").eq("order_customer_id", ogre.get("order_customer_id")).queryForList();
            List<String> orderVendorGoodsStatusList = orderVendorGoodsNew.stream().map(t -> (String) t.get("order_vendor_goods_status")).collect(Collectors.toList());
            //全部商品为已关闭==单据则为已关闭
            if (orderVendorGoodsStatusList.stream().allMatch(t -> t.equals(OrderGoodsStatusEnum.Closed.name()))) {
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR).putFieldAndVal("order_vendor_status", OrderGoodsStatusEnum.Closed.name()).eq("id", ogre.get("order_vendor_id")).update();
            }
            List<Map<String, Object>> orderCustomerGoodsNew = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS)
                    .selectField("*").eq("order_customer_id", ogre.get("order_customer_id")).queryForList();
            List<String> orderCustomerGoodsStatusList = orderCustomerGoodsNew.stream().map(t -> (String) t.get("order_customer_goods_status")).collect(Collectors.toList());
            //全部商品为已关闭==单据则为已关闭
            if (orderCustomerGoodsStatusList.stream().allMatch(t -> t.equals(OrderGoodsStatusEnum.Closed.name()))) {
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).putFieldAndVal("order_customer_status", OrderGoodsStatusEnum.Closed.name()).eq("id", ogre.get("order_customer_id")).update();
            }
        }
    }

    /**
     * 客户退货(客户订单详情-提交退货物流)
     * cn/gomro/core/bizes/order/service/impl/OrdersService.goodsReturn
     *
     * @param orderCustomerGoodsIds
     * @param logistics
     * @param waybill
     * @return
     */
    @Override
    public Map<String,List<String>> goodsReturn(List<String> orderCustomerGoodsIds, String logistics, String waybill) {
        List<Map<String, Object>> goodsReturnsList = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURNS).selectField("*")
                .in("order_customer_goods_id", orderCustomerGoodsIds).eq("order_goods_returns_status", OrderGoodsReturnsStatusEnum.ReturnPending.name()).queryForList();
        if (CollectionUtils.isEmpty(goodsReturnsList)) throw new RuntimeException("退货记录不存在！");

        List<String> refundIdList = new ArrayList<>();
        List<String> traceIdList = new ArrayList<>();
        for (Map<String, Object> goodsReturns : goodsReturnsList) {
            // 退货记录中的扩展字段售后记录增加一条
            Map<String, Object> extendsAttr = Objects.isNull(goodsReturns.get("extends_attr")) ? null : JSON.parseObject((String) goodsReturns.get("extends_attr"), HashMap.class);
            List<Map<String, Object>> logs = new ArrayList<>();
            Map<String, Object> log = new HashMap<>();
            if (!CollectionUtils.isEmpty(extendsAttr)) {
                logs = JSON.parseObject(JSON.toJSONString(extendsAttr.get("logs")), ArrayList.class);
            } else {
                extendsAttr = new HashMap<>();
            }
            //退货记录中的扩展字段的售后过程增加一条记录
            log.put("operator", RequestContext.getLoginRealName());
            log.put("operatorUserId", RequestContext.getLoginId());
            log.put("behavior", BehaviorEnum.RETURN.getText());
            log.put("architectureName", organizationFeignService.listLabelByUserId(RequestContext.getCorpLoginId()).getData().get(0).getName());
            log.put("memo", "客户填写退货物流信息");
            log.put("time", DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
            logs.add(log);
            extendsAttr.put("logs", logs);
            //修改退货记录状态为已发退货
            JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURNS).putFieldAndVal("order_goods_returns_status", OrderGoodsReturnsStatusEnum.ReturnedDoneDelivery.name())
                    .putFieldAndVal("extends_attr", JSON.toJSONString(extendsAttr)).eq("id", goodsReturns.get("id")).update();
            //客户填写退货物流      -》label改为：已退货
            this.editOrderLabel(StrUtil.str(goodsReturns.get("order_customer_goods_id"), Charset.defaultCharset()),
                    StrUtil.str(goodsReturns.get("order_vendor_goods_id"), Charset.defaultCharset()),OrderApproveStatusEnum.RETIRED);
            refundIdList.add(goodsReturns.get("id").toString());
            //新增类型为退货类型的发货记录
            List<Map<String, Object>> orderTraces = new ArrayList<>();
            Map<String, Object> orderTrace = new HashMap<>();
            orderTrace.put("type", TraceTypeEnum.ReturnLogistics.toString());
            orderTrace.put("logistics", logistics);
            orderTrace.put("freight", BigDecimal.ZERO);
            orderTrace.put("arrival_time", null);
            orderTrace.put("quantity", BigDecimalUtils.round(goodsReturns.get("quantity"), 6));
            orderTrace.put("order_vendor_goods_id", goodsReturns.get("order_vendor_goods_id"));
            orderTrace.put("order_customer_goods_id", goodsReturns.get("order_customer_goods_id"));
            orderTrace.put("order_customer_id", goodsReturns.get("order_customer_id"));
            orderTrace.put("order_vendor_id", goodsReturns.get("order_vendor_id"));
            //其他字段赋值
            Map<String, Object> orderCustomerGoods = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS)
                    .selectField("*").in("id", goodsReturns.get("order_customer_goods_id")).queryForMap();
            Object customer_organization_id = orderCustomerGoods.get("customer_organization_id");
            orderTrace.put("customer_organization_id", Objects.isNull(customer_organization_id) ? null : JSON.parseObject((String) customer_organization_id, SelectorFormat.class));
            orderTrace.put("customer_organization_name", orderCustomerGoods.get("customer_organization_name"));
            Object vendor_organization_id = orderCustomerGoods.get("customer_organization_id");
            orderTrace.put("vendor_organization_id", Objects.isNull(vendor_organization_id) ? null : JSON.parseObject((String) vendor_organization_id, SelectorFormat.class));
            SelectorFormat send = getSelectorFormat(null, UnitType.USER);
            orderTrace.put("sender_id", send);
            orderTrace.put("sender_fullname", send.getName());
            Object place_order_user_id = orderCustomerGoods.get("vendor_organization_id");
            orderTrace.put("recipient_id", Objects.isNull(place_order_user_id) ? null : JSON.parseObject((String) place_order_user_id, SelectorFormat.class));
            orderTrace.put("recipient_fullname", orderCustomerGoods.get("vendor_organization_name"));
            orderTrace.put("quantity_received", BigDecimalUtils.round(BigDecimalUtils.isNull(orderCustomerGoods.get("quantity_received")), 6));
            orderTrace.put("name", orderCustomerGoods.get("name"));
            orderTrace.put("quantity_unit", BigDecimalUtils.round(BigDecimalUtils.isNull(orderTrace.get("quantity")), 0) + "/" + orderCustomerGoods.get("unit"));
            if (StringUtils.isNotBlank(waybill)) {
                String[] waybills = org.springframework.util.StringUtils.delimitedListToStringArray(waybill, "/");
                for (String wb : waybills) {
                    orderTrace.put("waybill", wb);
                    Map<String, Object> orderTraceNew = MapBuilder.create(new HashMap<String, Object>()).putAll(orderTrace).build();
                    orderTraces.add(orderTraceNew);
                }
            }
            SingleResponse<BO> bo = BoServiceUtils.createBo(ModelConst.T_ORDER_TRACE, orderTraces);
            if (bo.isSuccess()) {
                traceIdList.add(bo.getData().getBizObjectId());
            }

        }
        Map<String, List<String>> results = new HashMap<>();
        results.put("refundIds", refundIdList);
        results.put("transportIds",traceIdList);
        return results;
    }

    /**
     * 判断当前供应商是否为虚拟供应商
     *
     * @return
     */
    @Override
    public boolean isVirtual(SelectorFormat dept) {
        if (null == dept) {
            return false;
        }
        Map<String, Object> organization = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_ORGANIZATION)
                .selectField("*").eq("id", dept.getId()).queryForMap();
        if (!CollectionUtils.isEmpty(organization) && !Objects.isNull(organization.get("virtual")) && organization.get("virtual").toString().equals("1")) {
            return true;
        }
        return false;
    }

    /**
     * 通过商品ID获取报价商品信息
     *
     * @return
     */
    @Override
    public Map<String, Object> getQuotationGoods(String goodsId) {
        if (StringUtils.isBlank(goodsId)) {
            return null;
        }
        Map<String, Object> quotationGoods = null;
        Map<String, Object> goodsPurchase = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODS_PURCHASE).selectField("*").eq("id", goodsId).queryForMap();
        if (null != goodsPurchase) {
            quotationGoods = JdbcTemplateUtils.builder(AppConst.SOURCING_CENTER, ModelConst.T_QUOTATION_GOODS).selectField("*").eq("id", goodsPurchase.get("quotation_goods_id")).queryForMap();
        }
        return quotationGoods;
    }

    /**
     * 平台修改退款单
     * cn/gomro/core/bizes/order/service/impl/OrdersService.editRefund
     *
     * @param refundId
     * @param amount
     * @param num
     * @param memo
     * @return
     */
    @Override
    public SingleResponse<BO> editRefund(String refundId, BigDecimal amount, BigDecimal num, String memo) {

        if (null == amount || BigDecimal.ZERO.compareTo(amount) > -1 || null == num || BigDecimal.ZERO.compareTo(num) > -1)
            throw new RuntimeException("数据无效，请重新输入！");
        Map<String, Object> ogre = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RETURNS)
                .selectField("*").eq("id", refundId).queryForMap();

        BigDecimal refundableNum = getRefundableNum((String) ogre.get("order_customer_goods_id"));

        BigDecimal actualRefundableNum = BigDecimalUtils.add(refundableNum, BigDecimalUtils.isNull(ogre.get("quantity")));

        if (num.compareTo(actualRefundableNum) == 1) throw new RuntimeException("调整数量不可大于可退数量！");
        //更新退货记录表数据，退货记录表状态为未退货
        Map<String, Object> ogreParam = new HashMap<>();
        memo = Objects.isNull(memo) ? "" : memo;
        ogreParam.put("customer_amount", amount);
        ogreParam.put("quantity", num);
        ogreParam.put("memo", memo);
        ogreParam.put("id", refundId);
        SingleResponse<BO> response = BoServiceUtils.updateMainBo(ModelConst.T_ORDER_GOODS_RETURNS, ogreParam);
        //修改对应客户、订单商品中的已退数量
        return response;
    }

    /**
     * 根据消耗创建订单(订单中心-寄售消耗统计-消耗待结算明细-生成订单)
     *
     * @param idList
     * @return
     */
    @Override
    public SingleResponse buildVmiOrder(List<String> idList) {
        if (null == idList || idList.isEmpty()) throw new RuntimeException("明细id为空!");
        List<Map<String, Object>> sbmeList = JdbcTemplateUtils.builder(AppConst.JISHOU, ModelConst.T_STOCK_BILL_MATERIAL)
                .selectField("*").in("id", idList).queryForList();
        if (null == sbmeList || sbmeList.isEmpty()) throw new RuntimeException("明细单据不存在!");

        Map<String, Object> customerOrder = new HashMap<>();
        List<Map<String, Object>> vendorOrders = new ArrayList<>();

        List<String> idsList = new ArrayList<>();

        List<StockBillMaterialDto> stockBillMaterialVOS = new ArrayList<>();
        for (Map<String, Object> sme : sbmeList) {

            //非客户承担不结算
            if (!sme.get("bear_type").equals(BearTypeEnum.CUSTOMER_BEAR.name())) {
                continue;
            }

            //非盘亏、非领用、非退料不结算
            if (!sme.get("type").equals(StockBillMaterialTypeEnum.CHECK_LOSS.name()) && !sme.get("type").equals(StockBillMaterialTypeEnum.USE.name()) && !sme.get("type").equals(StockBillMaterialTypeEnum.RETURN.name())) {
                continue;
            }

            //参与结算的记录
            idsList.add((String) sme.get("id"));

            if (null == stockBillMaterialVOS || stockBillMaterialVOS.isEmpty()) {
                stockBillMaterialVOS.add(new StockBillMaterialDto(JSON.parseObject((String) sme.get("vendor_id"), SelectorFormat.class), (String) sme.get("goods_id"), BigDecimalUtils.isNull(sme.get("num"))));
            } else {
                Boolean flag = true;
                for (StockBillMaterialDto sbmVOS : stockBillMaterialVOS) {
                    if (sbmVOS.getGoodsId().equals(sme.get("goods_id"))) {
                        sbmVOS.setNum(BigDecimalUtils.add(sbmVOS.getNum(), BigDecimalUtils.isNull(sme.get("num"))));
                        flag = false;
                    }
                }
                if (flag) {
                    stockBillMaterialVOS.add(new StockBillMaterialDto(JSON.parseObject((String) sme.get("vendor_id"), SelectorFormat.class), (String) sme.get("goods_id"), BigDecimalUtils.isNull(sme.get("num"))));
                }
            }
        }
        //创建订单
        //整理消耗数据，订单处理完后，通过此ids改变原单据状态
        String ids = org.apache.commons.lang3.StringUtils.join(idsList, ",");
        customerOrder.put("vmi_ids", ids);
        //先按照供应商分组，相同供应商分到一组
        Map<SelectorFormat, List<StockBillMaterialDto>> sbmVendorGroup = stockBillMaterialVOS.stream().collect(Collectors.groupingBy(StockBillMaterialDto::getVendorId));
        sbmVendorGroup.forEach((vendorId, sbmVendor) -> {
            List<Map<String, Object>> orderGoodsList = new ArrayList<>();
            //再按照商品ID分组，相同商品一组，并求和
            Map<String, List<StockBillMaterialDto>> sbmGoodsGroup = sbmVendor.stream().collect(Collectors.groupingBy(StockBillMaterialDto::getGoodsId));
            sbmGoodsGroup.forEach((goodsId, sbmGoods) -> {
                Map<String, Object> orderGoods = new HashMap<>();

                BigDecimal num = new BigDecimal(sbmGoods.stream().mapToDouble(m -> m.getNum().doubleValue()).sum());

                Map<String, Object> goods = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODS_PURCHASE)
                        .selectField("*").eq("id", goodsId).queryForMap();
                if (CollectionUtils.isEmpty(goods)) throw new RuntimeException("来源vmi商品不存在！");

                //最大库存量
                Map<String, Object> inquiryGoods = getInquiryGoodsByGoodsId(goodsId);
                String costCenterName = null == inquiryGoods || inquiryGoods.isEmpty() ? null : (String) inquiryGoods.get("cost_center_name");

                orderGoods.put("category", null == goods.get("catalog") ? "" : goods.get("catalog"));
                orderGoods.put("brand", goods.get("brand"));
                orderGoods.put("name", goods.get("name"));
                orderGoods.put("model", goods.get("model"));
                orderGoods.put("spec", goods.get("spec"));
                orderGoods.put("sku", null == goods.get("customer_sku") ? "" : goods.get("customer_sku"));
                orderGoods.put("bar_code", goods.get("vendor_bar_code"));
                orderGoods.put("golden_tax", goods.get("golden_tax"));
                orderGoods.put("unspsc", goods.get("unspsc"));
                orderGoods.put("images", Optional.ofNullable(goods.get("images")).orElse(""));
                orderGoods.put("description", goods.get("description"));
                orderGoods.put("technical", "");
                orderGoods.put("packaging", "");
                orderGoods.put("unit", goods.get("unit"));
                orderGoods.put("package_unit", goods.get("package_unit"));
                orderGoods.put("package_num", goods.get("package_num"));
                orderGoods.put("warranty", "");
                orderGoods.put("delivery", goods.get("delivery"));
                orderGoods.put("length", null);
                orderGoods.put("width", null);
                orderGoods.put("height", null);
                orderGoods.put("weight", null);
                orderGoods.put("cost_center_name", costCenterName);
                orderGoods.put("demand_goods_id", null);

                orderGoods.put("num", num);
                //VMI下单即完成，则商品发货数量和收货数量为下单数量
                orderGoods.put("quantity_shipped", num);
                orderGoods.put("quantity_received", num);

                orderGoods.put("tax_rate", goods.get("tax_rate"));
                orderGoods.put("pretax_freight", goods.get("pretax_freight"));
                orderGoods.put("tax_rate_freight", goods.get("tax_rate_freight"));
                orderGoods.put("pretax_price", goods.get("pretax_price"));

                orderGoods.put("order_customer_goods_status", OrderGoodsStatusEnum.UpcomingPayment.name());

                orderGoods.put("goods_id", goodsId);
                orderGoods.put("cart_src", com.authine.cloudpivot.ext.enums.CartSrcEnum.VMI.id);
                orderGoods.put("goods_src", CartSrcEnum.VMI.id);
                orderGoods.put("delivery_time", null);
                orderGoods.put("customer_account_period", 0);
                orderGoods.put("vendor_account_period", 0);
                orderGoods.put("customer_period_time", null);
                orderGoods.put("vendor_period_time", null);
                orderGoods.put("attachment", null);
                orderGoods.put("client_order_goods_id", "");

                orderGoods.put("vendor_organization_id", vendorId);
                orderGoods.put("clarify_tips", null);
                orderGoods.put("cost_center_name", null);
                orderGoods.put("region", null);
                orderGoods.put("company", null);
                orderGoods.put("warehouse", null);
                orderGoods.put("deliveryRequirements", null);
                orderGoods.put("demand_goods_id", null);

                // 计算
                orderGoods.put("tax_payable_freight", ObjectUtil.defaultIfNull(goods.get("pretax_price"), FinancialCalculationUtils.calculateTaxPayableByPretaxPrice(BigDecimalUtils.isNull(goods.get("pretax_price")), BigDecimalUtils.isNull(goods.get("tax_rate")), num)));
                orderGoods.put("tax_payable", ObjectUtil.defaultIfNull(goods.get("pretax_price"), FinancialCalculationUtils.calculatePayableFreightByPretaxFreight(BigDecimalUtils.isNull(goods.get("pretax_freight")), BigDecimalUtils.isNull(goods.get("tax_rate_freight")))));
                orderGoods.put("price", FinancialCalculationUtils.calculatePriceByPretaxPrice(BigDecimalUtils.isNull(goods.get("pretax_price")), BigDecimalUtils.isNull(goods.get("tax_rate"))));
                orderGoods.put("freight", FinancialCalculationUtils.calculateFreightByPretaxFreight(BigDecimalUtils.isNull(goods.get("pretax_freight")), BigDecimalUtils.isNull(goods.get("tax_rate_freight"))));
                orderGoods.put("pretax_total", FinancialCalculationUtils.calculatePretaxTotalByPretaxPrice(BigDecimalUtils.isNull(goods.get("pretax_price")), num));
                orderGoods.put("total", FinancialCalculationUtils.calculateTotalByPretaxPrice(BigDecimalUtils.isNull(goods.get("pretax_price")), BigDecimalUtils.isNull(goods.get("tax_rate")), num));
                orderGoods.put("pretax_amount", FinancialCalculationUtils.calculatePretaxAmountByPretaxPriceAndPretaxFreight(BigDecimalUtils.isNull(goods.get("pretax_price")), BigDecimalUtils.isNull(goods.get("pretax_freight")), num));
                orderGoods.put("amount", FinancialCalculationUtils.calculateAmountByPretaxPriceAndPretaxFreight(BigDecimalUtils.isNull(goods.get("pretax_price")), BigDecimalUtils.isNull(goods.get("pretax_freight")), BigDecimalUtils.isNull(goods.get("tax_rate")), BigDecimalUtils.isNull(goods.get("tax_rate_freight")), num));
                orderGoodsList.add(orderGoods);
            });
            Map<String, Object> vendorOrderEntity = new HashMap<>();
            vendorOrderEntity.put("vendor_id", vendorId);
            vendorOrderEntity.put("organization_name", vendorId.getName());
            vendorOrderEntity.put("order_vendor_status", OrderVendorStatusEnum.UpcomingPayment.name());
            vendorOrderEntity.put("account_period", 0);
            vendorOrderEntity.put("orders_time", null);
            vendorOrderEntity.put("memo", "");

            //获取供应商用户信息
            if (null != vendorId) {
                vendorOrderEntity.put("orders_member", vendorId.getId());
                vendorOrderEntity.put("member_name", vendorId.getName());
                vendorOrderEntity.put("user_name", vendorId.getName());
            }
            // 计算
            vendorOrderEntity.put("tax_rate", ObjectUtil.defaultIfNull(vendorOrderEntity.get("tax_rate"), 0.16));
            vendorOrderEntity.put("tax_rate_freight", ObjectUtil.defaultIfNull(vendorOrderEntity.get("tax_rate_freight"), 0.0));
            vendorOrderEntity.put("tax_payable", orderGoodsList.stream().filter(t -> !Objects.isNull(t.get("tax_payable"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax_payable")).doubleValue()).sum());
            vendorOrderEntity.put("tax_payable_freight", orderGoodsList.stream().filter(t -> !Objects.isNull(t.get("tax_payable_freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax_payable_freight")).doubleValue()).sum());
            vendorOrderEntity.put("pretax_freight", orderGoodsList.stream().filter(t -> !Objects.isNull(t.get("pretax_freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_freight")).doubleValue()).sum());
            vendorOrderEntity.put("freight", orderGoodsList.stream().filter(t -> !Objects.isNull(t.get("freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("freight")).doubleValue()).sum());
            vendorOrderEntity.put("pretax_total", orderGoodsList.stream().filter(t -> !Objects.isNull(t.get("pretax_total"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_total")).doubleValue()).sum());
            vendorOrderEntity.put("total", orderGoodsList.stream().filter(t -> !Objects.isNull(t.get("total"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("total")).doubleValue()).sum());
            vendorOrderEntity.put("pretax_amount", orderGoodsList.stream().filter(t -> !Objects.isNull(t.get("pretax_amount"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_amount")).doubleValue()).sum());
            vendorOrderEntity.put("amount", orderGoodsList.stream().filter(t -> !Objects.isNull(t.get("amount"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("amount")).doubleValue()).sum());
            vendorOrderEntity.put("orderGoodsList", orderGoodsList);
            vendorOrders.add(vendorOrderEntity);
        });

        // 计算
        customerOrder.put("tax_rate", ObjectUtil.defaultIfNull(customerOrder.get("tax_rate"), 0.16));
        customerOrder.put("tax_rate_freight", ObjectUtil.defaultIfNull(customerOrder.get("tax_rate_freight"), 0.16));
        customerOrder.put("tax_payable", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("tax_payable"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax_payable")).doubleValue()).sum());
        customerOrder.put("tax_payable_freight", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("tax_payable_freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("tax_payable_freight")).doubleValue()).sum());
        customerOrder.put("pretax_freight", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("pretax_freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_freight")).doubleValue()).sum());
        customerOrder.put("freight", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("freight"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("freight")).doubleValue()).sum());
        customerOrder.put("pretax_total", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("pretax_total"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_total")).doubleValue()).sum());
        customerOrder.put("total", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("total"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("total")).doubleValue()).sum());
        customerOrder.put("pretax_amount", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("pretax_amount"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_amount")).doubleValue()).sum());
        customerOrder.put("amount", vendorOrders.stream().filter(t -> !Objects.isNull(t.get("amount"))).mapToDouble(t -> BigDecimalUtils.isNull(t.get("amount")).doubleValue()).sum());

        customerOrder.put("cart_id", "");
        customerOrder.put("cartIds", idList.size());
        customerOrder.put("erp_po", "");
        //个人收货信息
        List<Map<String, Object>> deliverAddressList = JdbcTemplateUtils.builder(AppConst.PERSONAL_CENTER, ModelConst.T_MEMBER_DELIVER_ADDRESS).selectField("*")
                .eq("default_address", true).eq("member_id -> '$.id'", RequestContext.getCorpLoginId()).queryForList();
        if (!CollectionUtils.isEmpty(deliverAddressList)) {
            Map<String, Object> deliverAddress = deliverAddressList.get(0);
            customerOrder.put("receiver", deliverAddress.get("receiver_name"));
            customerOrder.put("phone", deliverAddress.get("mobile"));
            customerOrder.put("address", ObjectUtil.defaultIfNull(deliverAddress.get("area"), "") + " " + ObjectUtil.defaultIfNull(deliverAddress.get("address"), ""));
            customerOrder.put("postal", deliverAddress.get("post"));
        } else {
            customerOrder.put("receiver", "");
            customerOrder.put("phone", "");
            customerOrder.put("address", "");
            customerOrder.put("postal", "");
        }
        customerOrder.put("account_period", 0);
        customerOrder.put("customer_id", BoResultFormat.getMainDept(RequestContext.getCorpLoginId()));
        customerOrder.put("vendorOrders", vendorOrders);
        return SingleResponse.of(customerOrder);
    }

    @Override
    public SingleResponse orderBeforCondition(final Map<String, Object> data) {

        //todo  判断 只有客户角色才可创建订单!
        String corpLoginId = RequestContext.getCorpLoginId();

        //todo  当前组织必须存在客户管理员角色
        //todo  如果开启了超期未开票属性，需要根据当前组织调用财务是否存在产生收货账单后超过三十天没有申请开票，如果有则不通过
        //todo 当前组织必须存在结算组织
        //todo 获取结算组织，并且结算组织的账户不能为空（t_organization.account_id notnull），结算组织的账期不能为空并且不能小于0（t_organization.statement_cycle notnull &&>=0）
        //todo 如果商品来源类型为单次时，需要验证当前下单人所属的权限（userAapi.listSubMemberIds()）必须包含下单商品对应询价人用户ID，但是如果当前用户拥有权限XXX（名称暂未定义，做好后会补充）则此验证跳过（ps 这里的验证逻辑感觉跨越所属权限了，因为下单商品来源有好几种，这种商品的验证交给不同种类的商品接口内部去处理即可）


        return SingleResponse.of(true);
    }

    @Override
    public SingleResponse submitOrder(final Map<String, Object> orderCustomer) {
        //供应商订单
        List<Map<String, Object>> orderVendorList = (List<Map<String, Object>>) orderCustomer.get("vendorOrders");

        if (null == orderVendorList || orderVendorList.isEmpty()) {
            return SingleResponse.buildFailure("-1", "订单数据错误");
        }
        //企业采购目录 ids
        List<String> goodsIds = new ArrayList<>();
        //商品来源
        StringBuilder goodsSrc = new StringBuilder("");

        //需求商品ids
        List<String> demandIds = new ArrayList<>();
        //订单关系
        List<Map<String, Object>> relationList = new ArrayList<>();
        orderCustomer.put("relationList", relationList);

        //客户订单商品
        final List<Map<String, Object>> custGoodsList = new ArrayList<>();

        //获取商品来源状态
        if (!CollectionUtils.isEmpty(orderVendorList)) {
            List<Map<String, Object>> orderGoodsList = (List<Map<String, Object>>) orderVendorList.get(0).get("orderGoodsList");
            if (!CollectionUtils.isEmpty(orderGoodsList)) {
                goodsSrc.append(GoodsSrcEnum.switchNew(Integer.valueOf(orderGoodsList.get(0).get("goods_src").toString())).name());
                ;

            }
        }

        //todo 1客户订单、供应商订单、客户订单商品和供应商订单商品状态为未付款，如果为VMI订单（寄售下单），则订单状态为已完成
        if (null != goodsSrc && GoodsSrcEnum.Vmi.name().equals(goodsSrc.toString())) {
            orderCustomer.put("order_customer_status", OrderCustomerStatusEnum.Done.name());
        } else {
            orderCustomer.put("order_customer_status", OrderCustomerStatusEnum.UpcomingPayment.name());
        }

        BoResultFormat.initSys(RequestContext.getCorpLoginId(), orderCustomer);
        SelectorFormat customer_id = JSON.parseObject(JSON.toJSONString(orderCustomer.get("customer_id")), SelectorFormat.class);

        orderCustomer.put("custGoodsList", custGoodsList);

        orderVendorList.forEach(a -> {
            //todo1
            if (null != goodsSrc && GoodsSrcEnum.Vmi.name().equals(goodsSrc.toString())) {
                a.put("order_vendor_status", OrderVendorStatusEnum.Done.name());
            } else {
                a.put("order_vendor_status", OrderVendorStatusEnum.UpcomingPayment.name());
            }
            SelectorFormat vendor_id = Objects.isNull(a.get("vendor_id")) ? null : JSON.parseObject(JSON.toJSONString(a.get("vendor_id")), SelectorFormat.class);
            a.put("organization_id", vendor_id);
            a.put("organization_name", vendor_id.getName());
            a.put("order_customer_id", orderCustomer.get("id"));
            a.put("erp_po", orderCustomer.get("erp_po"));
            a.put("after_sale", "未售后");
            BoResultFormat.initSys(RequestContext.getCorpLoginId(), a);

            //客户订单商品和供应商订单商品来源类型是 单次寻源 | 多次寻源,取源商品账期；客户订单商品和供应商订单商品来源类型是 代购 | VMI | 市场,取结算账户账期
            Integer accountPeriod = Integer.valueOf(a.get("account_period").toString());

            ((List<Map<String, Object>>) a.get("orderGoodsList")).forEach(b -> {
                //todo1
                if (null != goodsSrc && GoodsSrcEnum.Vmi.name().equals(goodsSrc.toString())) {
                    b.put("order_customer_goods_status", OrderGoodsStatusEnum.Done.name());
                    b.put("order_vendor_goods_status", OrderGoodsStatusEnum.Done.name());
                } else {
                    b.put("order_customer_goods_status", OrderGoodsStatusEnum.UpcomingPayment.name());
                    b.put("order_vendor_goods_status", OrderGoodsStatusEnum.UpcomingPayment.name());
                }
                //需求池id是否存在
                if (!Objects.isNull(b.get("demand_goods_id"))) {
                    demandIds.add((String) b.get("demand_goods_id"));
                }


                //企业采购目录ids
                goodsIds.add((String) b.get("goods_id"));

//                if (goodsSrc.length() == 0) {
//                    goodsSrc.append(b.get("goods_src"));
//                }

                //订单关系表
                Map<String, Object> relation = null == b.get("relation_id") ? new HashMap<>() : (Map<String, Object>) b.get("relation_id");
                BoResultFormat.initSys(RequestContext.getCorpLoginId(), relation);

                relation.put("delivery_requirements", b.get("delivery_requirements"));

                relationList.add(relation);

                b.put("relation_id", relation.get("id"));
                BoResultFormat.initSys(vendor_id.getId(), b);

                b.put("order_customer_id", orderCustomer.get("id"));
                b.put("order_vendor_id", a.get("id"));

                b.put("customer_organization_id", customer_id);
                b.put("customer_organization_name", null == customer_id ? null : customer_id.getName());
                b.put("vendor_organization_id", vendor_id);
                b.put("vendor_organization_name", null == vendor_id ? null : vendor_id.getName());
                String images = "[]";
                if (!Objects.isNull(b.get("images"))) {
                    images = b.get("images") instanceof String ? (String) b.get("images") : JSON.toJSONString(b.get("images"));
                }
                b.put("images", images);
                b.put("erp_po", orderCustomer.get("erp_po"));
                //数量
                b.put("quantity", b.get("num"));
                //初始化数量
                //已发货数量
                b.put("quantity_shipped", ObjectUtil.defaultIfNull(b.get("quantity_shipped"), 0.0));
                //已收货数量
                b.put("quantity_received", ObjectUtil.defaultIfNull(b.get("quantity_received"), 0.0));
                //已退未发数量
                b.put("quantity_return_not_shipped", 0.0);
                //已退已发数量
                b.put("quantity_return_shipped", 0.0);
                //仅退收货数量
                b.put("returned_num", 0.0);
                //退的收货部分的数量
                b.put("return_received_num", 0.0);
                //退给平台的收货部分的数量
                b.put("return_pm_received_num", 0.0);
                //数量/单位
                if (!Objects.isNull(b.get("quantity")) && !Objects.isNull(b.get("unit"))) {
                    b.put("quantity_unit", b.get("quantity") + "/" + b.get("unit"));
                }
                //包装数量/单位
                if (!Objects.isNull(b.get("package_quantity")) && !Objects.isNull(b.get("unit"))) {
                    b.put("package_quantity_unit", b.get("package_quantity") + "/" + b.get("unit"));
                }
                //标记信息
//                Map<String, Object> quotationGoods = getQuotationGoods((String) b.get("goods_id"));
//                b.put("remark_message", CollectionUtils.isEmpty(quotationGoods) ?
//                        null : quotationGoods.get("remark_message"));

                //4如果是寻源过来的商品需要从询价单上的账期赋值到订单商品的客户账期字段（customer_account_period）
                b.put("customer_account_period", accountPeriod);
                b.put("vendor_account_period", accountPeriod);
                //商品来源
                b.put("goods_src", GoodsSrcEnum.switchNew(Integer.valueOf(b.get("goods_src").toString())).name());
                //税率*100
//                b.put("tax_rate", b.get("tax_rate"));

                //todo1;todo2
                Map<String, Object> custOrderGoods = MapBuilder.create(new HashMap<String, Object>()).putAll(b).build();


                BoResultFormat.initSys(RequestContext.getCorpLoginId(), custOrderGoods);
                custOrderGoods.put("id", SchemaHelper.getId());

                custGoodsList.add(custOrderGoods);

            });
        });
        //超出100条给提示：下单物料数量不超过100条，请拆分物料下单，谢谢
        if (custGoodsList.size()> 100){
            throw new BizException("下单物料数量不超过100条，请拆分物料下单，谢谢!");
        }
        //done  2由于页面显示的时候是面对客户所以只构建了客户订单商品，后台需要copy客户订单商品到供应商订单商品，除了商品ID不同，目前客户订单商品和供应商订单商品一致

        //todo 3这里需要重复获取企业采购目录商品的信息验证商品信息过期时间没有过期
        Integer expireCount = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODS_PURCHASE)
                .selectField(" count(1) as count  ")
                .in("id", goodsIds)
                .lt("expire", new Date())
                .queryForObject(Integer.class);

        if (expireCount > 0) {
            return SingleResponse.buildFailure("-1", "商品已过期");
        }

        //todo 5持久化客户订单、供应商订单、客户订单商品、供应商订单商品、订单商品关系表(t_order_goods_relation)
        if (null == orderCustomer.get("type")) {
            orderCustomer.put("type", OrderTypeEnum.PurchaseOrder.name());
        } else if (null != goodsSrc && GoodsSrcEnum.Vmi.name().equals(goodsSrc.toString())) {
            orderCustomer.put("type", OrderTypeEnum.VmiOrder.name());
        }

        orderCustomer.put("organization_id", customer_id);
        orderCustomer.put("organization_name", !Objects.isNull(customer_id) ? customer_id.getName() : null);
        orderCustomer.put("place_order_user_id", Utils.createSelecorFormat(RequestContext.getCorpLoginId(), RequestContext.getLoginRealName(), 3));
        orderCustomer.put("place_order_fullname", RequestContext.getLoginRealName());
        orderCustomer.put("after_sale", "未售后");
        //TODO 测试默认开始,等7供应商对应流程做好，判断为对应订单，再将enabled=false
        orderCustomer.put("enabled", true);

        //添加平台组织id
        if (null != customer_id && null != customer_id.getId()) {
            Map<String, Object> organization = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_ORGANIZATION)
                    .selectField("*").eq("id", customer_id.getId()).queryForMap();
            orderCustomer.put("platform_id", null == organization ? null : organization.get("platform_id"));
        }

        //判断供应商组织是否是小规模纳税人,如果是，重新计算供应商订单商品及订单金额
        this.calculateOrderMap(orderCustomer);
//        orderCustomer.put("vendorOrders", this.calculateVendorOrderMap(orderVendorList));

        //创建订单
        saveOrder(orderCustomer);

        //订单-》转采
        toTransferOrder((String) orderCustomer.get("id"));

        //todo 6如果开启了付款审批，则不做任何操作，否则需要调用订单付款接口，详见订单付款接口

        //todo 8如果是vmi订单，需要系统自动调用发货和收货，因为vmi这是生成一个完整的已完成订单，订单并不需要操作订单的流程
        //  --调用 vmi 自动发货和收货

        //done 9
        // --1. 如果当前下单不是VMI类型，需要从客户订单中取出购物车ID，调用删除购物车方法（这里目前是异步，所以如果订单失败了，需要回滚该数据）
        boolean isNotVmi = !GoodsSrcEnum.Vmi.name().equals(goodsSrc.toString());
        List<Map<String, Object>> purchaseList = null;
        if (isNotVmi) {
            List<String> cart_id = (List<String>) orderCustomer.get("cart_id");

            if (cart_id != null && cart_id.size() > 0) {
                //获取采购清单信息
                purchaseList = JdbcTemplateUtils.builder(ModelConst.T_CART)
                        .selectField(" goods_id as id,quantity as num")
                        .in("id", cart_id)
                        .in("goods_src", Arrays.asList(CartSrcEnum.SINGLE.id, CartSrcEnum.LOOP.id))
                        .queryForList();

                //修改清单为已删除
                JdbcTemplateUtils.builder(ModelConst.T_CART)
                        .putFieldAndVal("deleted", 1)
                        .in("id", cart_id)
                        .update();
            }
        }

        //done 10
        // --2. 如果不是vmi订单，并且是企业采购目录商品下单，需要回写企业采购目录数据，这里属于商品模块，我先写到此处，逻辑是：
        // -- 根据下单成功后的购物车ID获取企业采购目录商品（t_goods_purchase）;
        // -- 如果商品类型为单次（t_goods_purchase.type=SINGLE）时，修改商品字段是否可用为不可用（t_goods_purchase.enabled=false），并且已买数量等于下单数量，也就是加入购物车数量（t_goods_purchase.bought=t_cart.num）
        // -- 如果商品类型为多次时（t_goods_purchase.type=LOOP）,修改商品已买数量为累加（t_goods_purchase.bought+t_cart.num）,修改Last时间为当前时间

        if (purchaseList != null && purchaseList.size() > 0) {
            Map<String, Integer> purchaseMap = purchaseList.stream().collect(Collectors.groupingBy(a -> MapUtils.getString(a, "id"), Collectors.summingInt(a -> MapUtils.getIntValue(a, "num"))));

//            Map<String, Object> purchaseMap = purchaseList.stream().collect(Collectors.toMap(a -> (String) a.get("id"), a -> a.get("num"), (k1, k2) -> k1));

            List<Map<String, Object>> updateList = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODS_PURCHASE)
                    .selectField(" id,bought,type")
                    .in("id", purchaseMap.keySet().stream().collect(Collectors.toList()))
                    .queryForList();

            updateList.forEach(a -> {
                GoodsPurchaseTypeEnum goodsType = GoodsPurchaseTypeEnum.get(MapUtils.getInteger(a, "type"));
                if (GoodsPurchaseTypeEnum.SINGLE == goodsType) {
                    a.put("enabled", 0);
                    //采购数量
                    Integer num = purchaseMap.get((String) a.get("id"));
                    a.put("bought", num);
                } else if (GoodsPurchaseTypeEnum.LOOP == goodsType) {
                    //采购数量
                    Integer num = purchaseMap.get((String) a.get("id"));
                    int bought = MapUtils.getIntValue(a, "bought");
                    a.put("bought", bought + num);
                }
                JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODS_PURCHASE)
                        .putFieldAndVal(a)
                        .eq("id", a.get("id"))
                        .update();
            });

        }

        //DONE 11如果商品信息中有需求商品ID（demand_goods_id）,需要调用更改需求商品状态和需求单状态，该修改方法请寻源需求模块提供
        //设置需求池商品matching为true,状态为已转订单
        if (!demandIds.isEmpty()) {

            updateDemandGoods(demandIds);
        }
        log.info("发起订单流程order_approval_flow，订单id::{}", orderCustomer.get("id"));
        workflowService.startWorkflowInstance("order_approval_flow", orderCustomer.get("id").toString(), RequestContext.getCorpLoginId(), orderCustomer.get("createdDept").toString(), true, "", "", "");

        //如果是振德组织需要推送给振德系统下单数据，这里是同步的，因为要求他们那下单成功我们这才能成功，他们那下单失败我们这也要失败
        try {
            toZhenDe(orderCustomer);
        } catch (Exception e) {
            //推送失败，订单回滚时同时回滚财务的交易记录
            /*List<Long> orderGoodsIds = new ArrayList<>();
            for (VendorOrderEntity vendorOrder : customerOrder.getVendorOrderList()) {
                orderGoodsIds.addAll(vendorOrder.getGoodsList().stream().map(BaseEntity::getId).map(Long::valueOf).collect(Collectors.toList()));
            }
            String logParam = org.apache.commons.lang3.StringUtils.join(orderGoodsIds, ",");
            log.warn("订单创建异常触发交易回滚：回滚开始--->商品编号{}", logParam);
            RestResponse<String> rollback = tradeApi.rollback(orderGoodsIds);
            if (200 == rollback.getCode()) {
                log.warn("订单创建异常触发交易回滚：回滚成功--->商品编号{}", logParam);
            } else {
                log.warn("订单创建异常触发交易回滚：回滚失败--->商品编号{}", logParam);
            }*/
            throw new RuntimeException(e);
        }
        return SingleResponse.of(true);
    }

    private void updateDemandGoods(List<String> demandIds) {
        demandIds.forEach(a -> {
            String demand_pool_id = JdbcTemplateUtils.builder(AppConst.DEMAND_POOL, ModelConst.T_DEMAND_GOODS)
                    .selectField(" demand_pool_id ")
                    .eq("id", a)
                    .queryForObject(String.class);

            if (StringUtils.isNotBlank(demand_pool_id)) {
                //把当前需求商品的状态改为  已转订单
                JdbcTemplateUtils.builder(AppConst.DEMAND_POOL, ModelConst.T_DEMAND_GOODS)
                        .putFieldAndVal("demand_goods_status", DemandGoodsStatusEnum.DEMAND_GOODS_3_ORDER.getCode())
                        .eq("id", a)
                        .update();


                // 通过需求池id 获取 需求商品的商品状态
                List<String> demand_goods_status = JdbcTemplateUtils.builder(AppConst.DEMAND_POOL, ModelConst.T_DEMAND_GOODS)
                        .selectField(" demand_goods_status ")
                        .eq("demand_pool_id", demand_pool_id)
                        .queryForList(String.class);

                String status = DemandPoolStatusEnum.DEMAND_6_EXECUTE_ALL.getCode();
                if (demand_goods_status != null) {
                    for (String b : demand_goods_status) {
                        if (!b.equals(DemandGoodsStatusEnum.DEMAND_GOODS_3_ORDER) && !b.equals(DemandGoodsStatusEnum.DEMAND_GOODS_2_INQUIRY)) {

                            // 需求池的状态
                            status = DemandPoolStatusEnum.DEMAND_5_EXECUTE_PART.getCode();
                            break;
                        }
                    }
                }

                //执行修改
                JdbcTemplateUtils.builder(AppConst.DEMAND_POOL, ModelConst.T_DEMAND_POOL)
                        .putFieldAndVal("demand_pool_status", status)
                        .eq("id", demand_pool_id)
                        .update();
            }
        });


    }

    private void saveOrder(final Map<String, Object> orderCustomer) {


        //客户订单
        Map<String, Object> cust = MapBuilder.create(new HashMap<String, Object>()).putAll(orderCustomer).build();


        //客户订单商品
        List<Map<String, Object>> custGoodsList = (List<Map<String, Object>>) cust.remove("custGoodsList");

        //供应商订单
        List<Map<String, Object>> orderVendorList = (List<Map<String, Object>>) cust.remove("vendorOrders");
        //供应商订单商品表
        List<Map<String, Object>> vendorGoodsList = new ArrayList<>();
        orderVendorList.forEach(a -> {
            List<Map<String, Object>> orderGoodsList = (List<Map<String, Object>>) a.remove("orderGoodsList");
            vendorGoodsList.addAll(orderGoodsList);
        });


        //订单关系表
        List<Map<String, Object>> relationList = (List<Map<String, Object>>) cust.remove("relationList");


        log.info("===============\n");
        log.info("===============客户订单=\n{}", cust);
        log.info("===============\n");
        log.info("===============客户订单商品=\n{}", custGoodsList);
        log.info("===============\n");
        log.info("===============供应商订单=\n{}", orderVendorList);
        log.info("===============\n");
        log.info("===============供应商订单商品=\n{}", vendorGoodsList);
        log.info("===============\n");
        log.info("===============订单关系表=\n{}", relationList);

        List<String> split = new ArrayList<>();
        split.addAll(cust.keySet());
        split.removeAll(Arrays.asList(OrderCenterTableField.t_order_customer.split(",")));
        split.forEach(b -> cust.remove(b));

        // 把 SelectorFormat Map List 序列化
        ObjectFunction selectorConvert = (a) -> {
            Map.Entry<String, Object> entry = (Map.Entry<String, Object>) a;

            if (entry.getValue() == null) {
                return entry;
            }
            if (entry.getValue() instanceof SelectorFormat
                    || entry.getValue() instanceof List
                    || entry.getValue() instanceof Map) {
                entry.setValue(JSON.toJSONString(entry.getValue()));
            }


            return entry;
        };


        cust.entrySet().forEach(selectorConvert::convert);

        //客户订单save
        JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER)
                .putFieldAndVal(cust)
                .insert();


        //客户订单商品save
        split.clear();
        custGoodsList.forEach(a -> {
            if (split.isEmpty()) {
                split.addAll(a.keySet());
                split.removeAll(Arrays.asList(OrderCenterTableField.t_order_customer_goods.split(",")));
            }

            split.forEach(b -> a.remove(b));

            a.entrySet().forEach(selectorConvert::convert);
            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER_GOODS)
                    .putFieldAndVal(a)
                    .insert();
        });


        //供应商订单表save
        split.clear();
        orderVendorList.forEach(a -> {
            if (split.isEmpty()) {
                split.addAll(a.keySet());
                split.removeAll(Arrays.asList(OrderCenterTableField.t_order_vendor.split(",")));
            }
            split.forEach(b -> a.remove(b));

            a.entrySet().forEach(selectorConvert::convert);
            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR)
                    .putFieldAndVal(a)
                    .insert();
        });


        //供应商商品订单订单表save
        split.clear();
        vendorGoodsList.forEach(a -> {
            if (split.isEmpty()) {
                split.addAll(a.keySet());
                split.removeAll(Arrays.asList(OrderCenterTableField.t_order_vendor_goods.split(",")));
            }
            split.forEach(b -> a.remove(b));
            a.entrySet().forEach(selectorConvert::convert);
            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR_GOODS)
                    .putFieldAndVal(a)
                    .insert();
        });

        //订单关系表save
        split.clear();
        relationList.forEach(a -> {
            if (split.isEmpty()) {
                split.addAll(a.keySet());
                split.removeAll(Arrays.asList(OrderCenterTableField.t_order_goods_relation.split(",")));
            }
            split.forEach(b -> a.remove(b));
            a.entrySet().forEach(selectorConvert::convert);
            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_RELATION)
                    .putFieldAndVal(a)
                    .insert();
        });
    }

    /**
     * 普通订单-》转采订单
     *
     * @param orderCustomerId
     * @return
     */
    @Override
    public void toTransferOrder(String orderCustomerId) {
        if (StringUtils.isNotBlank(orderCustomerId)) {
            return;
        }
        Map<String, Object> orderCustomer = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).selectField("*").eq("id", orderCustomerId).queryForMap();
        //客户订单商品
        List<Map<String, Object>> custGoodsList = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).selectField("*")
                .eq("order_customer_id", orderCustomerId).queryForList();
        //供应商订单
        List<Map<String, Object>> orderVendorList = JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR).selectField("*")
                .eq("order_customer_id", orderCustomerId).queryForList();
        //判断是否为虚拟供应商
        List<Map<String, Object>> voList = orderVendorList.stream().filter(t -> isVirtual(Objects.isNull(t.get("organization_id")) ? null : JSON.parseObject((String) t.get("organization_id"), SelectorFormat.class))).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(voList)) {
//            BigDecimal total = BigDecimalUtils.round(BigDecimalUtils.isNull(voList.stream().mapToDouble(t -> BigDecimalUtils.isNull(t.get("total")).doubleValue()).sum()), 2);
//            BigDecimal preTotal = BigDecimalUtils.round(BigDecimalUtils.isNull(voList.stream().mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_total")).doubleValue()).sum()), 2);
//            BigDecimal amount = BigDecimalUtils.round(BigDecimalUtils.isNull(voList.stream().mapToDouble(t -> BigDecimalUtils.isNull(t.get("amount")).doubleValue()).sum()), 2);
//            BigDecimal preAmount = BigDecimalUtils.round(BigDecimalUtils.isNull(voList.stream().mapToDouble(t -> BigDecimalUtils.isNull(t.get("pretax_amount")).doubleValue()).sum()), 2);

            Map<String, Object> transferOrder = new HashMap<>();
            String platformId = null;
            String platformName = null;
            String orderType = custGoodsList.get(0).get("goods_src").equals(GoodsSrcEnum.Contract) ? OrderType.Contract.name() : OrderType.Purchase.name();
            SelectorFormat memberId = ObjectUtil.defaultIfNull((SelectorFormat) orderCustomer.get("place_order_user_id"), null);
            transferOrder.put("member_id", JSON.toJSONString(memberId));
            transferOrder.put("cloud_order_id", orderCustomer.get("id"));
            transferOrder.put("user_name", ObjectUtil.defaultIfNull(memberId.getName(), null));
            SelectorFormat organizationId = ObjectUtil.defaultIfNull((SelectorFormat) orderCustomer.get("organization_id"), null);
            transferOrder.put("organization_id", JSON.toJSONString(organizationId));
            transferOrder.put("organization_name", ObjectUtil.defaultIfNull(organizationId.getName(), null));
            transferOrder.put("account_period", custGoodsList.get(0).get("customer_account_period"));
            transferOrder.put("tax_rate", orderCustomer.get("tax_rate"));
            transferOrder.put("total", orderCustomer.get("total"));
            transferOrder.put("pre_total", orderCustomer.get("pretax_total"));
            transferOrder.put("amount", orderCustomer.get("amount"));
            transferOrder.put("pre_amount", orderCustomer.get("pretax_amount"));
            transferOrder.put("receiver", orderCustomer.get("receiver"));
            transferOrder.put("phone", orderCustomer.get("phone"));
            transferOrder.put("postal", orderCustomer.get("postal"));
            transferOrder.put("address", orderCustomer.get("address"));
            transferOrder.put("pay_time", orderCustomer.get("place_order_time"));
            transferOrder.put("order_type", orderType);
            transferOrder.put("is_contract", StringUtils.isNotBlank(orderType) && orderType.equals(OrderType.Contract.name()) ? true : false);
            transferOrder.put("transfer_order_status", OrderCustomerStatusEnum.UpcomingPayment.name());
            transferOrder.put("erp_po", orderCustomer.get("erp_po"));
            if (null != organizationId) {
                Map<String, Object> organization = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_ORGANIZATION).eq("id", organizationId.getId()).queryForMap();
                if (!CollectionUtils.isEmpty(organization)) {
                    platformId = Objects.isNull(organization.get("platform_id")) ? null : JsonParseObject.parseObject((String) organization.get("platform_id"), SelectorFormat.class).get(0).getId();
                    platformName = CollectionUtils.isEmpty(organization) ? null : (String) organization.get("platform_name");
                    transferOrder.put("platform_id", platformId);
                    transferOrder.put("platform_name", platformName);
                }
            }
            BoResultFormat.initSys(RequestContext.getCorpLoginId(), transferOrder);
            JdbcTemplateUtils.builder(AppConst.ZHUANCAI, ModelConst.T_TRANSFER_ORDER).putFieldAndVal(transferOrder).insert();

            for (Map<String, Object> voe : voList) {
                List<Map<String, Object>> orderGoodsList = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER_GOODS).selectField("*").eq("order_customer_id", voe.get("order_customer_id")).queryForList();
                SelectorFormat vendorId = ObjectUtil.defaultIfNull(JSON.parseObject((String) voe.get("organization_id"), SelectorFormat.class), null);
                for (Map<String, Object> oge : orderGoodsList) {
                    Map<String, Object> transferOrderGoods = MapBuilder.create(new HashMap<String, Object>())
                            //状态转换
                            .put("transfer_order_goods_status", oge.get("order_customer_goods_status"))
                            .put("cloud_order_goods_id", oge.get("id"))
                            .put("vendor_id", JSON.toJSONString(vendorId))
                            .put("vendor_name", ObjectUtil.defaultIfNull(vendorId.getName(), null))
                            .put("category", oge.get("category"))
                            .put("brand", oge.get("brand"))
                            .put("name", oge.get("name"))
                            .put("model", oge.get("model"))
                            .put("spec", oge.get("spec"))
                            .put("sku", oge.get("sku"))
                            .put("memo", oge.get("description"))
                            .put("unit", oge.get("unit"))
                            .put("delivery", oge.get("delivery"))
                            .put("num", oge.get("quantity"))
                            .put("price", oge.get("price"))
                            .put("pre_price", oge.get("pretax_price"))
                            .put("freight", oge.get("freight"))
                            .put("tax_rate", oge.get("tax_rate"))
                            .put("total", oge.get("total"))
                            .put("pre_total", oge.get("pretax_total"))
                            .put("amount", oge.get("amount"))
                            .put("not_purchase", false)
                            .put("pre_amount", oge.get("pretax_amount")).build();
                    //询价商品id
                    if (null != oge.get("relation_id")) {
                        Map<String, Object> orderGoodsRelation = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_RELATION).selectField("*")
                                .eq("id", oge.get("relation_id")).queryForMap();
                        if (orderGoodsRelation != null) {
                            transferOrderGoods.put("inquiry_id", orderGoodsRelation.get("inquiry_td"));
                        }
                    }
                    transferOrderGoods.put("remark_message", CollectionUtils.isEmpty(getQuotationGoods((String) oge.get("goods_id"))) ? null : getQuotationGoods((String) oge.get("goods_id")).get("remark_message"));
                    transferOrderGoods.put("platform_name", platformName);
                    transferOrderGoods.put("order_type", orderType);
                    transferOrderGoods.put("cloud_order_id", orderCustomer.get("id"));
                    transferOrderGoods.put("user_name", ObjectUtil.defaultIfNull(memberId.getName(), null));
                    transferOrderGoods.put("organization_name", ObjectUtil.defaultIfNull(organizationId.getName(), null));
                    BoResultFormat.initSys(RequestContext.getCorpLoginId(), transferOrderGoods);
                    transferOrderGoods.put("transfer_order_id", transferOrder.get("id"));
                    JdbcTemplateUtils.builder(AppConst.ZHUANCAI, ModelConst.T_TRANSFER_ORDER_GOODS).putFieldAndVal(transferOrderGoods).insert();
                }
            }
        }
    }

    /**
     * 封装数据 发给振德
     *
     * @param customerOrder
     */
    public void toZhenDe(Map<String, Object> customerOrder) {
        String organizationName = (String) customerOrder.get("organization_name");
        String erpPO = (String) customerOrder.get("erp_po");

        // 是以下组织才调用振德系统下订单：河南振德医疗用品有限公司(3232) 、 许昌振德医用敷料有限公司(3231)、 振德医疗用品股份有限公司(2928)、 许昌正德医疗用品有限公司(3230)、 绍兴好士德医疗用品有限公司(4207)
        if (Sets.newHashSet("河南振德医疗用品有限公司", "许昌振德医用敷料有限公司", "振德医疗用品股份有限公司", "许昌正德医疗用品有限公司", "绍兴好士德医疗用品有限公司").contains(organizationName)) {
            // 振德 新基地的单子不走振德 如果erp po 为空并且不是xinjidi的话 才走调用振德下单
            log.info("erp po:{}", erpPO);
            if (!Objects.isNull(erpPO) && !erpPO.equals("xinjidi")) {
                String orderOrganizationName = (String) customerOrder.get("organization_name");
                List<PushOrderGoodsModel> pushOrderGoodsModelList = new ArrayList<>();
                List<PushOrderUpdateModel> pushOrderUpdateModelList = new ArrayList<>();
                List<Map<String, Object>> vendorOrderList = (ArrayList) customerOrder.get("vendorOrders");
                UserDto member = UserUtils.getUserByUserId(((SelectorFormat) customerOrder.get("member_id")).getId());

                vendorOrderList.forEach(e -> ((ArrayList<Map<String, Object>>) e.get("orderGoodsList")).forEach(orderGoods -> {
                    Date d = new Date();
                    SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
                    Calendar ca = Calendar.getInstance();
                    ca.add(Calendar.DATE, Objects.isNull(orderGoods.get("delivery")) ? 0 : (Integer) orderGoods.get("delivery"));// num为增加的天数，可以改变的
                    d = ca.getTime();
                    BigDecimal round = BigDecimalUtils.round(BigDecimalUtils.mul(orderGoods.get("pretax_price"), 10000), 2);
                    DecimalFormat decimalFormat = new DecimalFormat("#.00");
                    String pretaxPrice = decimalFormat.format(round);
                    String zhenDeCode = getZhenDeCode(orderOrganizationName, member.getJob_number());
                    if (zhenDeCode.equals("2050") && member.getJob_number().equals("312")) {
                        zhenDeCode = "2051";
                    }
                    PushOrderGoodsModel pushOrderGoodsModel = PushOrderGoodsModel.builder()
                            .matnr((String) orderGoods.get("sku")) // 物料编号
                            .werks(zhenDeCode) // 工厂
                            .menge(Double.valueOf(orderGoods.get("num").toString())) // 采购商品数量
                            .peinh(10000)
                            .netpr(pretaxPrice) // 采购单价
                            .mwskz(orderGoods.get("tax_rate").equals("0.13") ? "J7" : "") // 税率
                            .eindt(format.format(d)) // 货期
                            .build();
                    pushOrderGoodsModelList.add(pushOrderGoodsModel);
                    PushOrderUpdateModel orderUpdateModel = PushOrderUpdateModel.builder()
                            .itemNumber((String) orderGoods.get("sku"))
                            .invoicingSpecifications(Double.valueOf(orderGoods.get("tax_rate").toString()))
                            .specificationModel(orderGoods.get("spec") + "" + orderGoods.get("model"))
                            .brand((String) orderGoods.get("brand"))
                            .productName((String) orderGoods.get("name"))
                            .build();
                    pushOrderUpdateModelList.add(orderUpdateModel);
                }));
                String zhenDeOrg = getZhenDeCode(orderOrganizationName, member.getJob_number());
                PushOrderModel pushOrderModel = PushOrderModel.builder()
                        .bsart("ZD20") // 类型
                        .lifnr("500775") // 固买在振德的的编码 - 500775
                        .ekorg(zhenDeOrg) //下单组织名称
                        .ekgrp(member.getJob_number()) //下单人名称
                        .bukrs(zhenDeOrg) //下单组织名称
                        .zfornum("固买：" + customerOrder.get("id")) //订单编号
                        .pushOrderGoodsModelList(pushOrderGoodsModelList)
                        .build();

                // 修改振德订单商品 ---
                log.warn("调用振德修改接口请求信息：{}", pushOrderUpdateModelList);
                zhendeService.pushOrderUpdate(pushOrderUpdateModelList);
                // 下订单信息推送给振德 返回的信息 判断是不是请求成功了 失败的话抛异常给页面
                log.warn("调用振德下单接口请求信息：{}", pushOrderModel);
                String returnXml = zhendeService.pushOrder(pushOrderModel);
                OrderResultModel data = zhendeService.XmlToObject(returnXml);
                log.warn("调用振德下单接口返回信息：{}", data);
                // 调用失败
                if (null == data) {
                    throw new RuntimeException("调用振德接口失败!,请联系管理员!");
                }
                String evtype = data.getEvtype();
                if (null == evtype || !evtype.equals("S")) {
                    throw new RuntimeException("振德系统下单失败：" + data.getEvmess());
                }
                // 接收 orderResultModelRestResponse 取值 反写到 订单的erp po
                String evebeln = data.getEvebeln();
                customerOrder.put("erp_po", null == evebeln ? "" : evebeln);
                JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).putFieldAndVal("erp_po", null == evebeln ? "" : evebeln)
                        .eq("id", customerOrder.get("id")).update();
                try {
                    List<TradeErpPoUpdate> tradeErpPoUpdate = Collections.singletonList(TradeErpPoUpdate.builder().customerOrderId((String) customerOrder.get("id")).erpPo(evebeln).build());
                    dockFinanceService.writeBackErpPo(tradeErpPoUpdate);
                } catch (Exception e) {
                    log.warn("振德订单编号{}反写财务交易ERPPO异常", customerOrder.get("id"));
                }
            }
        }
    }

    /**
     * 根据组织和采购人编码查询振德给出的振德系统编码
     *
     * @param orgName
     * @param jobNumber
     * @return 振德系统编号
     * 采购对应编码  赵艳伟 308、宋彦辉 312、宋志晖 504、李亚培 505、曲校辉 905
     */
    public String getZhenDeCode(String orgName, String jobNumber) {
        if (orgName != null) {
            // 河南振德
            if (orgName.equals("振德医疗用品股份有限公司") && jobNumber.equals("504")) {
                return "2040";
            }
            if (orgName.equals("河南振德医疗用品有限公司")) {
                return "2040";
            }
            // 许昌振德
            if (orgName.equals("振德医疗用品股份有限公司") && (jobNumber.equals("312") || jobNumber.equals("308"))) {
                return "2050";
            }
            if (orgName.equals("许昌振德医用敷料有限公司")) {
                return "2050";
            }
            // 许昌正德
            if (orgName.equals("振德医疗用品股份有限公司") && jobNumber.equals("905")) {
                return "3010";
            }
            if (orgName.equals("许昌正德医疗用品有限公司")) {
                return "3010";
            }
            // 绍兴好士德
            if (orgName.equals("绍兴好士德医疗用品有限公司")) {
                return "1000";
            }
        }
        return "";
    }

    /**
     * 接受vo创建订单（第三方系统创建订单）
     * cn/gomro/core/bizes/order/service/impl/OrdersService.createOrder(OrderVo order)
     *
     * @param orderVo
     * @return
     */
    @Override
    public IOrderCustomerVO iCreateOrder(final CustomerOrderVo orderVo) {
        //创建临时对象
        IOrderCustomerVO orderCustomer = buildOrder(orderVo);
        //保存对象
        orderCustomer.setType(OrderTypeEnum.ClientOrder.name());

        IOrderCustomerVO orderCustomerVO = transactionTemplate.execute(transactionStatus -> createOrder(orderCustomer));

        //获取来源不是外部商城订单，也就是寻源定标商品
        List<String> quotationGoodsIds = orderVo.getCustomerOrderGoodsVo().stream()
                .filter(t -> !"4".equals(t.getGoods_src())).map(CustomerOrderGoodsVo::getGoods_id).collect(Collectors.toList());
        List<GoodsPurchaseEntity> goodsPurchaseList = null;
        if (!CollectionUtils.isEmpty(quotationGoodsIds)) {

            String goodsPurchaseT = JdbcTemplateUtils.getTableName(ModelConst.T_GOODS_PURCHASE, AppConst.COMMODITYMATERIALS);
            String quotationGoodsT = JdbcTemplateUtils.getTableName(ModelConst.T_QUOTATION_GOODS, AppConst.SOURCING_CENTER);

            StringBuilder st = new StringBuilder(" SELECT purchase.* FROM ");
            st.append(goodsPurchaseT);
            st.append(" purchase LEFT JOIN  ");
            st.append(quotationGoodsT);
            st.append(" quotation  ON  purchase.quotation_goods_id = quotation.id WHERE purchase.del = FALSE AND purchase.enabled = TRUE AND purchase.enabled = TRUE ");
            st.append(" AND  quotation.id IN ( :quotation_goods_id ) ");

            Map<String, Object> queryParam = new HashMap<>();
            queryParam.put("quotation_goods_id", quotationGoodsIds);

            log.info("sql:{}",st);
            log.info("queryParam:{}",queryParam);

            List<Map<String, Object>> mapList = JdbcTemplateUtils.queryForList(st.toString(), queryParam);
            if (!CollectionUtils.isEmpty(mapList)) {
                goodsPurchaseList = mapList.stream().map(e->BeanUtil.mapToBean(e, GoodsPurchaseEntity.class, true)).collect(Collectors.toList());
            }

        }

        for (CustomerOrderGoodsVo ogv : orderVo.getCustomerOrderGoodsVo()) {
            if (!"4".equals(ogv.getGoods_src())) {

                if (CollectionUtils.isEmpty(goodsPurchaseList)) {
                    throw new BizException("未获取到需要回写的企业采购商品");
                }
                GoodsPurchaseEntity goodsPurchase = goodsPurchaseList.stream()
                        .filter(t -> t.getQuotation_goods_id().equals(ogv.getGoods_id())).findFirst().orElseThrow(() -> new BizException("商品未找到"));

                if ("2".equals(ogv.getGoods_src())) {
                    goodsPurchase.setEnabled(false);
                    goodsPurchase.setBought(ogv.getNum());

                } else if ("3".equals(ogv.getGoods_src())) {
                    goodsPurchase.setBought(BigDecimalUtils.add(ogv.getNum(), goodsPurchase.getBought()));
                    //第二次采购不限制最大采购量
                    goodsPurchase.setMaximum(null);
                }
                goodsPurchase.setModifiedTime(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
            } else {
                orderCustomerVO.setType(OrderTypeEnum.ShopOrder.name());
            }
        }

        if (!org.apache.commons.collections4.CollectionUtils.isEmpty(goodsPurchaseList)) {
            //todo 修改商品

        }

        return orderCustomerVO;
    }

    /**
     * 从数据传输对象创建订单临时对象
     * CustomerOrderVo ->  IOrderCustomerVO
     *
     * @param order
     * @return
     * @throws
     */
    public IOrderCustomerVO buildOrder(CustomerOrderVo order) throws BizException {
        if (null == order) throw new BizException("传输对象为空!");
        if (null == RequestContext.getCorpLoginId()) throw new BizException("未获取到登录信息!");
        SessionUser sessionUser = new SessionUser();
        if (null == sessionUser.get()) throw new BizException("未获取到登录信息!");

        String clientId = sessionUser.getCurrentClientID();
        String memberId = sessionUser.getCurrentUserId();
        String orgId = sessionUser.getCurrentOrgID();

        OrganizationDto orgAccount = OrgUtils.getOrgByOrgId(orgId);
        if (null == orgAccount) {
            throw new BizException("用户组织账户为空!");
        }
        if (null == order.getClient_order_id()) throw new BizException("请输入clientOrderId~");

        Integer count = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).selectField(" count(client_order_id) as count  ")
                .eq("client_order_id", order.getClient_order_id()).eq("client_id", clientId)
                .queryForObject(Integer.class);

        if (0 != count && !"gomro_api".equals(clientId) && !"gomro_ios".equals(clientId)) {
            throw new BizException("来源订单id：【" + order.getClient_order_id() + "】已存在,请更换!");
        }
        if (CollectionUtils.isEmpty(order.getCustomerOrderGoodsVo())) {
            throw new BizException("商品信息不存在!");
        }
        List<String> applyClientOrderGoodsIds = order.getCustomerOrderGoodsVo().stream().map(CustomerOrderGoodsVo::getClient_order_goods_id).collect(Collectors.toList());
        List<String> existClientOrderGoodsIds = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).selectField(" client_order_goods_id ")
                .in("client_order_goods_id", applyClientOrderGoodsIds).eq("JSON_UNQUOTE(place_order_user_id -> '$.id')", memberId)
                .queryForList(String.class);
        existClientOrderGoodsIds = Optional.ofNullable(existClientOrderGoodsIds).orElse(Collections.emptyList());

        //对接时，类型为寻源单次或多次时的goodsId是报价商品ID
        List<String> quotationGoodsIds = order.getCustomerOrderGoodsVo().stream()
                .filter(t -> Utils.strEqualsArr(t.getGoods_src(), "2", "3"))
                .map(CustomerOrderGoodsVo::getGoods_id)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        List<GoodsPurchaseEntity> goodsPurchaseList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(quotationGoodsIds)) {
            goodsPurchaseList.addAll(BoQueryUtils.Builder(ModelConst.T_GOODS_PURCHASE).condition().in("quotation_goods_id", quotationGoodsIds)
                    .rpc(AppConst.COMMODITYMATERIALS).listBO(GoodsPurchaseEntity.class).getContent());
        }

        List<String> verifyOrganizationIds = OrgUtils.getOrgListByOrgId(orgId).stream().map(OrganizationDto::getId).collect(Collectors.toList());

        IOrderCustomerVO orderCustomer = new IOrderCustomerVO();
        List<IOrderVendorVO> orderVendors = new ArrayList<>();

        for (CustomerOrderGoodsVo vo : order.getCustomerOrderGoodsVo()) {
            if (null == vo.getClient_order_goods_id()) throw new BizException("请输入clientOrderGoodsId~");

            //判断外部来源订单Id是否已存在
            long b = existClientOrderGoodsIds.stream().filter(t -> t.equals(vo.getClient_order_goods_id())).count();
            if (0 != b && !"gomro_api".equals(clientId) && !"gomro_ios".equals(clientId)) {
                throw new BizException("来源订单商品id：【" + vo.getClient_order_goods_id() + "】已存在,请更换!");
            }
            IOrderCustomerGoodsVO orderCustGoods = new IOrderCustomerGoodsVO();
            orderCustGoods.setGoods_src("1".equals(vo.getGoods_src()) ? GoodsSrcEnum.Shop.name() : "2".equals(vo.getGoods_src()) ? GoodsSrcEnum.SourcingSingle.name() : GoodsSrcEnum.SourcingLoop.name());
            OrderGoodsRelationEntity or = new OrderGoodsRelationEntity();

            String vendorId;
            List<SelectorFormat> vendor;
            if (null == vo.getGoods_id()) throw new BizException("请输入goodsId!");

            if (Utils.strEqualsArr(vo.getGoods_src(), "2", "3")) {

                GoodsPurchaseEntity goods = goodsPurchaseList.stream()
                        .filter(t -> vo.getGoods_id().equals(t.getQuotation_goods_id()))
                        .findFirst().orElseThrow(() -> new BizException("来源商品：" + vo.getClient_order_goods_id() + "不存在!"));

                if (!goods.getEnabled()) new BizException("来源商品：" + vo.getClient_order_goods_id() + "已不可采购，请重新询价！");
                //转换对象为LinkedHashMap，需要重新转换才能操作
                goods.setVendor_id(JsonParseObject.parseObject(JSON.toJSONString(goods.getVendor_id()), SelectorFormat.class));
                vendorId = Utils.getSelectorFormatId(goods.getVendor_id());
                vendor = goods.getVendor_id();
                BigDecimal taxRate = goods.getTax_rate();
                // 增加友好返回
                // GoodsPurchaseTypeEnum.SINGLE(1, "单次"), // 询价单次采购
                // GoodsPurchaseTypeEnum.LOOP(2, "循环"); // 询价循环采购
                // 商品来源类型 1 固买商城，2 寻源商品, 3 企业商城, 4 外部商城订单
                // 这应该是入参逻辑错误，实际应用中，应该封装内容，只暴露必要的参数
                // src 属性是系统产生，不需要参数也不需要“暗号验证”
                if ((!"2".equals(vo.getGoods_src()) && GoodsPurchaseTypeEnum.SINGLE.equals(goods.getType()))) {
                    throw new BizException("参数 src 非寻源商品(" + vo.getGoods_src() + ")，采购类型不能为单次采购(" + goods.getType() + ")，订单商品(name:" + vo.getName() + ",id:" + vo.getClient_order_goods_id() + ") 请检查!");
                }
                if (!"3".equals(vo.getGoods_src()) && GoodsPurchaseTypeEnum.LOOP.equals(goods.getType())) {
                    throw new BizException("参数 src 非企业商城(" + vo.getGoods_src() + ")，采购类型不能为循环采购(" + goods.getType() + ")，订单商品(name:" + vo.getName() + ",id:" + vo.getClient_order_goods_id() + ") 请检查!");
                }

                if (null == vo.getNum() || 0 >= vo.getNum().doubleValue() || (("2".equals(vo.getGoods_src()) && Math.abs(vo.getNum().doubleValue() - goods.getNum().doubleValue()) > 1e-6))) {
                    throw new BizException("原报价商品" + vo.getGoods_id() + "数量为" + goods.getNum() + "，提交的订单商品数量为" + vo.getNum() + " 数量不对应，请检查。");
                }

                goods.setCustomer_id(JsonParseObject.parseObject(JSON.toJSONString(goods.getCustomer_id()), SelectorFormat.class));
                if (!verifyOrganizationIds.contains(Utils.getSelectorFormatId(goods.getCustomer_id()))) {
                    log.error("操作了非自己组织的商品进行下单，商品编号{}", goods.getId());
                    throw new BizException("定标商品编号【" + goods.getQuotation_goods_id() + "】非当前组织下不可进行操作");
                }

                //年度采购，判断采购数量
                if ("3".equals(vo.getGoods_src())) {
                    //组织首次采购量大于等于询价量
                    boolean enabledAttribute = OrgAttributeUtils.isEnabledAttribute(orgId, OrganizationAttributeEnum.STRATEGY_MORE);

                    if (enabledAttribute && vo.getNum().compareTo(goods.getNum()) < 0) {
                        throw new BizException("订单商品：" + vo.getClient_order_goods_id() + "的采购数量需要大于等于起订量" + goods.getNum() + "!");
                    }
                }

                //数据为null则不验证，直接取平台数据，否则验证小数点后2位误差
                if (null != vo.getPretax_price()) {
                    BigDecimal orderGoodsPretaxPrice = BigDecimalUtils.round(vo.getPretax_price(), 2);
                    BigDecimal goodsPretaxPrice = BigDecimalUtils.round(goods.getPretax_price(), 2);
                    double vPretaxPrice = Math.abs(orderGoodsPretaxPrice.subtract(goodsPretaxPrice).doubleValue());
                    if (vPretaxPrice > 1e-6) {
                        throw new BizException("原报价商品" + vo.getGoods_id() + "税前为" + goodsPretaxPrice + "元，提交的订单商品税前为" + orderGoodsPretaxPrice + "元 金额不对应，请检查。");
                    }
                }
                if (null != vo.getTax_rate()) {

                    double vTaxRate = Math.abs(BigDecimalUtils.sub(BigDecimalUtils.round(vo.getTax_rate(), 2), BigDecimalUtils.round(taxRate, 2)).doubleValue());
                    if (vTaxRate > 1e-6) {
                        throw new BizException("原报价商品" + vo.getGoods_id() + "税率为" + taxRate + "，提交的订单商品税率为" + BigDecimalUtils.round(vo.getTax_rate(), 2) + " 税率不对应，请检查。");
                    }
                }

                if (null != vo.getFreight_rate()) {
                    double vTaxRateFreight = Math.abs(BigDecimalUtils.round(vo.getFreight_rate(), 2).subtract(BigDecimalUtils.round(goods.getTax_rate_freight(), 2)).doubleValue());
                    if (vTaxRateFreight > 1e-6) {
                        throw new BizException("来源商品：" + vo.getClient_order_goods_id() + "运费税率有误!");
                    }
                }

                if (null != vo.getPrice()) {
                    double orderGoodsPrice = BigDecimalUtils.round(vo.getPrice(), 2).doubleValue();
                    double goodsPrice = BigDecimalUtils.round(goods.getPrice(), 2).doubleValue();
                    double vPrice = Math.abs(orderGoodsPrice - goodsPrice);
                    // 这是个高手 1e-6 就是 0.000001 也就是 1 * 10^-6
                    // 这个要表达的意思 应该是 入参的价格与系统价格的误差不能大小这个数
                    if (vPrice > 1e-6) {
                        throw new BizException("原报价商品" + vo.getGoods_id() + "价格：" + goodsPrice + "元，提交的订单商品价格：" + orderGoodsPrice + "元 金额不对应，请检查。");
                    }
                }

                orderCustGoods.setCategory(goods.getCatalog());
                orderCustGoods.setBrand(goods.getBrand());
                orderCustGoods.setName(goods.getName());
                orderCustGoods.setModel(goods.getModel());
                orderCustGoods.setSpec(goods.getSpec());
                orderCustGoods.setSku(null == goods.getCustomer_sku() ? "" : goods.getCustomer_sku());
                orderCustGoods.setGolden_tax(null == goods.getGolden_tax() ? "" : goods.getGolden_tax());
                orderCustGoods.setUnspsc(null == goods.getUnspsc() ? "" : goods.getUnspsc());
                orderCustGoods.setImages(null == goods.getImages() ? Collections.emptyList() : goods.getImages());
                orderCustGoods.setDescription(null == goods.getDescription() ? "" : goods.getDescription());

                orderCustGoods.setDescription(goods.getDescription());
                orderCustGoods.setUnit(goods.getUnit());
                orderCustGoods.setPackage_unit(goods.getPackage_unit());
                orderCustGoods.setPackage_quantity(goods.getPackage_num());
                orderCustGoods.setDelivery(goods.getDelivery());
                orderCustGoods.setGoods_id(goods.getId());

                orderCustGoods.setQuantity(vo.getNum());
                orderCustGoods.setTax_freight(goods.getTax_rate_freight());
                orderCustGoods.setPretax_freight(goods.getPretax_freight());
                orderCustGoods.setTax_rate(taxRate);
                orderCustGoods.setPretax_price(goods.getPretax_price());
                orderCustGoods.setErp_po(orderCustomer.getErp_po());
                //初始化值
                orderCustGoods.setQuantity_shipped(BigDecimal.ZERO);
                orderCustGoods.setQuantity_received(BigDecimal.ZERO);
                orderCustGoods.setQuantity_return_not_shipped(BigDecimal.ZERO);
                orderCustGoods.setQuantity_return_shipped(BigDecimal.ZERO);
                orderCustGoods.setReturn_pm_received_num(BigDecimal.ZERO);
                orderCustGoods.setReturned_num(BigDecimal.ZERO);
                orderCustGoods.setReturn_received_num(BigDecimal.ZERO);

                //外部来源订单记录询价信息
                try {

                    InquiryGoodsEntity inquiryGoods = BoQueryUtils.Builder(ModelConst.T_QUOTATION_GOODS).condition().eq("id", goods.getQuotation_goods_id())
                            .rpc(AppConst.SOURCING_CENTER).listBO(InquiryGoodsEntity.class)
                            .getContent().stream().findFirst()
                            .orElseThrow(() -> new BizException(String.format("商品id:%s ,未找到询价商品信息,询价商品id:%s", goods.getId(), goods.getInquiry_goods_id())));

                    InquiryEntity inquiry = BoQueryUtils.Builder(ModelConst.T_QUOTATION_GOODS).condition().eq("id", goods.getQuotation_goods_id())
                            .rpc(AppConst.SOURCING_CENTER).listBO(InquiryEntity.class)
                            .getContent().stream().findFirst()
                            .orElseThrow(() -> new BizException(String.format("商品id:%s ,未找到询价信息,询价单id:%s", goods.getId(), goods.getInquiry_id())));

                    or.setInquiry_member_id(inquiry.getMember_id());
                    or.setInquiry_id(inquiry.getId());
                    or.setDemand_department_name(Utils.getSelectorFormatName(inquiryGoods.getDemand_department()));
                } catch (Exception e) {
                    log.error("\n异常信息: {}", e.getMessage(), e);
                }

            } else if ("4".equals(vo.getGoods_src())) {
                GoodsEntity goods = BoQueryUtils.Builder(ModelConst.T_GOODSES).condition().eq("id", vo.getGoods_id()).rpc(AppConst.COMMODITYMATERIALS)
                        .listBO(GoodsEntity.class).getContent().stream().findFirst().orElseThrow(() -> new BizException("外部订单订单商品不存在！！！"));
                log.warn("施耐德对接下单信息：{},当前clientId:{}", vo, sessionUser.getCurrentClientID());
                // 施耐德订单 走这里
                if (sessionUser.getCurrentClientID().equals(ApiClientConstants.SCHNEIDER)) {
                    // goods
                    orderCustGoods.setGoods_id(vo.getGoods_id());
                    vendorId = Utils.getSelectorFormatId(goods.getVendor_id());
                    vendor = goods.getVendor_id();
                    orderCustGoods.setGoods_src(GoodsSrcEnum.ExternalMall.name());
                    orderCustGoods.setCategory(goods.getCatalog());
                    orderCustGoods.setBrand(vo.getBrand());
                    orderCustGoods.setName(vo.getName());
                    orderCustGoods.setModel(vo.getModel());
                    orderCustGoods.setSpec(vo.getSpec());

                    orderCustGoods.setQuantity(vo.getNum());
                    orderCustGoods.setUnit(vo.getUnit());
                    orderCustGoods.setPackage_quantity(vo.getPackage_num());
                    orderCustGoods.setPackage_unit(vo.getPackage_unit());
                    orderCustGoods.setDelivery(vo.getDelivery());

                    orderCustGoods.setGolden_tax(vo.getGolden_tax());
                    orderCustGoods.setTax_rate(null == vo.getTax_rate() ? goods.getTax_rate() : vo.getTax_rate());
                    orderCustGoods.setPretax_freight(null == vo.getPretax_freight() ? BigDecimal.ZERO : vo.getPretax_freight());
                    orderCustGoods.setFreight_rate(null == vo.getFreight_rate() ? BigDecimal.ZERO : vo.getFreight_rate());

                    orderCustGoods.setPretax_price(TaxRateUtils.calculateTaxBefore(vo.getPrice(), goods.getTax_rate()));
                    orderCustGoods.setPrice(vo.getPrice());
                    orderCustGoods.setAmount(vo.getAmount());
                    orderCustGoods.setMemo(vo.getMemo());
                    orderCustGoods.setImages(null == goods.getImages() ? Collections.emptyList() : goods.getImages());
                } else {
                    // goods
                    vendorId = Utils.getSelectorFormatId(goods.getVendor_id());
                    vendor = goods.getVendor_id();
                    orderCustGoods.setGoods_src(GoodsSrcEnum.ExternalMall.name());
                    orderCustGoods.setCategory(goods.getCatalog());

                    orderCustGoods.setBrand(goods.getBrand());
                    orderCustGoods.setName(goods.getName());
                    orderCustGoods.setModel(goods.getModel());
                    orderCustGoods.setSpec(goods.getSpec());

                    orderCustGoods.setSku(null == goods.getSku() ? "" : goods.getSku());
                    orderCustGoods.setGolden_tax(null == goods.getGolden_tax() ? "" : goods.getGolden_tax());
                    orderCustGoods.setImages(null == goods.getImages() ? Collections.emptyList() : goods.getImages());

                    orderCustGoods.setDescription(goods.getDescription());
                    orderCustGoods.setUnit(goods.getUnit());
                    orderCustGoods.setPackage_unit(goods.getPackage_unit());
                    orderCustGoods.setPackage_quantity(goods.getPackage_num());
                    orderCustGoods.setDelivery(goods.getDelivery());
                    orderCustGoods.setGoods_id(goods.getId());
                    orderCustGoods.setFreight_rate(BigDecimal.ZERO);
                    orderCustGoods.setPretax_freight(BigDecimal.ZERO);
                    orderCustGoods.setTax_rate(goods.getTax_rate());
                    orderCustGoods.setQuantity(vo.getNum());
                    orderCustGoods.setPretax_price(TaxRateUtils.calculateTaxBefore(goods.getPrice(), goods.getTax_rate()));
                }
            } else {
                throw new BizException("商品来源不存在!");
            }

            or.setRegion(vo.getRegion());
            or.setCompany(vo.getCompany());
            or.setWarehouse(vo.getWarehouse());
            or.setClient_factory_code(RegexUtils.notNull(order.getClientFactoryCode()) ? order.getClientFactoryCode() : null);

            orderCustGoods.setOrderGoodsRelationVO(or);

            orderCustGoods.setExtends_attr(vo.getExtends_attr());

            orderCustGoods.setQuantity(vo.getNum());
            orderCustGoods.setClient_order_goods_id(null == vo.getClient_order_goods_id() ? "" : vo.getClient_order_goods_id());

            boolean existVendor = false;
            for (IOrderVendorVO orderVendor : orderVendors) {

                if (vendorId.equals(Utils.getSelectorFormatId(orderVendor.getOrganization_id()))) {

                    if (null == orderVendor.getOrderCustomerGoodsVO())
                        orderVendor.setOrderCustomerGoodsVO(new ArrayList<>());

                    for (IOrderCustomerGoodsVO og : orderVendor.getOrderCustomerGoodsVO()) {
                        if (orderCustGoods.getGoods_src().equals(og.getGoods_src()) && orderCustGoods.getGoods_id().equals(og.getGoods_id()))
                            throw new BizException("存在重复商品");
                    }

                    orderCustGoods.setOrderVendorVO(orderVendor);
                    orderVendor.getOrderCustomerGoodsVO().add(orderCustGoods);

                    existVendor = true;
                    break;
                }
            }

            if (!existVendor) {

                IOrderVendorVO orderVendor = new IOrderVendorVO();

                orderVendor.setOrganization_id(CollectionUtils.isEmpty(vendor) ? null : vendor.get(0));
                orderVendor.setAccountPeriod(orgAccount.getStatement_cycle() == null ? 0 : orgAccount.getStatement_cycle()); // 客户账期
                orderVendor.setPlace_order_time(DateUtils.getDate("yyyy-MM-dd HH:mm:ss"));
                orderVendor.setOrder_taker_id(null);
                orderVendor.setMemo(null == vo.getMemo() ? "" : vo.getMemo());
                orderVendor.setAfter_sale("未售后");

                orderVendor.setOrderCustomerGoodsVO(new ArrayList<>());
                orderCustGoods.setOrderVendorVO(orderVendor);
                orderVendor.getOrderCustomerGoodsVO().add(orderCustGoods);
                orderVendor.setOrderCustomerVO(orderCustomer);

                orderVendors.add(orderVendor);

            }
        }

        //建客户订单
        orderCustomer.setType(OrderTypeEnum.ClientOrder.name());
        orderCustomer.setClient_os(null == order.getClient_os() ? "" : order.getClient_os());
        orderCustomer.setOrderVendorVO(orderVendors);
        orderCustomer.setClient_user_id(null == order.getClient_user_id() ? "" : order.getClient_user_id());
        orderCustomer.setClient_id(clientId);
        orderCustomer.setClient_order_id(null == order.getClient_order_id() ? "" : order.getClient_order_id());
        orderCustomer.setPlace_order_user_id(sessionUser.getUserFormat());
        orderCustomer.setPayment_method(PaymentMethodEnum.Credit.name());
        orderCustomer.setErp_po(null == order.getErp_po() ? "" : order.getErp_po());
        orderCustomer.setReceiver(order.getReceiver());
        orderCustomer.setPhone(order.getPhone());
        orderCustomer.setAddress(order.getAddress());

        orderCustomer.setActual_order(order.getActual_order());
        orderCustomer.setExtends_attr(order.getExtends_attr());
        orderCustomer.setAfter_sale("未售后");
        orderCustomer.setEnabled(false);

        return orderCustomer;
    }

    /**
     * 接受vo创建订单
     *
     * @return
     */
    public IOrderCustomerVO createOrder(IOrderCustomerVO orderCustomer) throws BizException {

        //检测客户订单参数
        checkOrder(orderCustomer);

        SessionUser sessionUser = new SessionUser();
        if (null == sessionUser.get()) throw new BizException("未获取到登录信息!");

        String memberId = sessionUser.getCurrentUserId();
        String orgId = Optional.ofNullable(sessionUser.getCurrentOrgID()).orElseThrow(() -> new BizException("组织ID为空!"));

        OrganizationDto organization = Optional.ofNullable(OrgUtils.getOrgByOrgId(orgId)).orElseThrow(() -> new BizException("用户组织不可用!"));

        if (!sessionUser.isCustomer()) throw new BizException("只有客户角色才可创建订单!");

        boolean overdue = OrgAttributeUtils.isEnabledAttribute(orgId, OrganizationAttributeEnum.OVERDUE_BUT_NOT_INVOICED);
        if (overdue) {
            List<String> orgIds = Optional.ofNullable(OrgUtils.getOrgListByOrgId(orgId)).orElseThrow(() -> new BizException("获取的ID列表为空"))
                    .stream().map(OrganizationDto::getId).collect(Collectors.toList());

            StringBuilder billSql = new StringBuilder(" select * from ")
                    .append(JdbcTemplateUtils.getTableName(AppConst.FINANCIALCENTER, ModelConst.T_BILL)).append(" as bill ")
                    .append(" left join ").append(JdbcTemplateUtils.getTableName(AppConst.FINANCIALCENTER, ModelConst.T_TRADE)).append(" as trade on bill.trade_id = trade.id ")
                    .append(" where JSON_UNQUOTE(bill.organization_id -> '$.id') = :orgIds and trade.invoice_status =:invoiceStatus and bill.direction = :direction ");

            List<Map<String, Object>> billList = jdbcTemplate.queryForList(billSql.toString(),
                    MapBuilder.create(new HashMap<String, Object>())
                            .put("orgIds", orgIds)
                            .put("invoice_status", TradeInvoiceStatus.Undo.name())
                            .put("direction", TradeDirection.Sale.name()).build());

            Date now = new Date();
            Date delivery;

            for (final Map<String, Object> bill : billList) {
                Date bill_date = (Date) bill.get("bill_date");
                LocalDate parse = LocalDate.parse(DateFormatUtils.format(bill_date, "yyyy-MM-dd"));
                delivery = Date.from(parse.atStartOfDay(ZoneId.systemDefault()).toInstant());
                int day = (int) (now.getTime() - delivery.getTime()) / (1000 * 3600 * 24);
                if (day > 30) throw new BizException("部分商品已收货超30天，仍未申请开票,请前往申票，否则无法创建订单！");
            }
        }

        if (CollectionUtils.isEmpty(organization.getTransaction_organization_id())) {
            throw new BizException("请联系平台管理员添加客户结算组织!");
        }

        OrganizationDto tranOrg;
        String tranOrgId = organization.getTransaction_organization_id().get(0).getId();
        if (!organization.getId().equals(tranOrgId)) {
            tranOrg = Optional.ofNullable(OrgUtils.getOrgByOrgId(tranOrgId)).orElseThrow(() -> new BizException("未获取到对应的结算组织!"));
        } else {
            tranOrg = organization;
        }
        if (null == tranOrg.getAccount_id()) throw new BizException("结算组织账户不能为空，请联系管理员添加结算组织账户!");

        //客户账期
        if (null == tranOrg.getStatement_cycle() || tranOrg.getStatement_cycle() < 0)
            throw new BizException("请联系平台管理员添加客户账期!");
        BigDecimal cap = new BigDecimal(tranOrg.getStatement_cycle());

        //检查组织属性是否开启混合下单
        boolean noMixedOrder = OrgAttributeUtils.isEnabledAttribute(orgId, OrganizationAttributeEnum.NO_MIXED_ORDER);
        if (noMixedOrder) {
            GoodsSrcEnum compareSrc = null;
            for (IOrderVendorVO ordervendor : orderCustomer.getOrderVendorVO()) {
                final long uniqueSrcType = ordervendor.getOrderCustomerGoodsVO().stream().map(IOrderCustomerGoodsVO::getGoods_src)
                        .filter(t -> Arrays.asList(GoodsSrcEnum.SourcingSingle.name(), GoodsSrcEnum.SourcingLoop.name()).contains(t)).distinct().count();

                final IOrderCustomerGoodsVO firstOrderGoods = ordervendor.getOrderCustomerGoodsVO().get(0);
                if (uniqueSrcType == 2) {
                    throw new BizException("单次询价和年度询价禁止混合下单，请分开提交!");
                }
                //该验证是为了一个订单多个供应商订单下面的商品来源类型也要唯一
                if (null != compareSrc && !compareSrc.name().equals(firstOrderGoods.getGoods_src())) {
                    throw new BizException("单次询价和年度询价禁止混合下单，请分开提交!");
                }

                compareSrc = GoodsSrcEnum.valueOf(firstOrderGoods.getGoods_src());
            }
        }

        //设置客户订单属性->客户下单客户订单状态为待付款
        orderCustomer.setOrder_customer_status(OrderCustomerStatusEnum.UpcomingPayment.name());
        orderCustomer.setAccountPeriod(cap);

        if (null == orderCustomer.getType()) {
            orderCustomer.setType(OrderTypeEnum.PurchaseOrder.name());
        }
        orderCustomer.setPlace_order_user_id(sessionUser.getUserFormat());

        orderCustomer.setPlace_order_fullname(sessionUser.get().getFullname());
        orderCustomer.setOrganization_id(Utils.createSelecorFormat(organization.getId(), organization.getName(), UnitType.DEPARTMENT.getIndex()));
        orderCustomer.setOrganization_name(organization.getName());
        //平台组织id
        orderCustomer.setPlatformId(Utils.getSelectorFormatId(organization.getPlatform_id()));
        //平台组织名称
        orderCustomer.setPlatformName(Utils.getSelectorFormatName(organization.getPlatform_id()));

        orderCustomer.setUsername(RequestContext.getLoginName());

        orderCustomer.setReconciliationStatus(ReconciliationStatusEnum.UNDO);
        orderCustomer.setInvoiceStatus(InvoiceStatusEnum.UNDO);
        orderCustomer.setPaymentStatus(PaymentStatusEnum.UNDO);

        List<String> vendorIds = OrgUtils.listVendorByCustomerId(orgId);

        List<String> orderVendorIds = orderCustomer.getOrderVendorVO().stream().map(t -> t.getOrganization_id().getId()).collect(Collectors.toList());
        List<OrganizationDto> orderVendorOrgList = Optional.ofNullable(OrgUtils.getOrgListByOrgIds(orderVendorIds)).orElseThrow(() -> new BizException("获取供应商组织失败"));

        //寻源商品ids
        List<String> goodsPurchaseIds = orderCustomer.getOrderVendorVO().stream()
                .flatMap(o -> o.getOrderCustomerGoodsVO().stream().filter(g -> GoodsSrcEnum.sourcing().contains(GoodsSrcEnum.valueOf(g.getGoods_src()))).map(g -> g.getGoods_id()))
                .collect(Collectors.toList());

        List<PlaceOrderSourcingDTO> inquiryInfoList = new ArrayList<>();
        List<GoodsPurchaseEntity> goodsPurchaseList = Collections.emptyList();
        if (!CollectionUtils.isEmpty(goodsPurchaseIds)) {
            goodsPurchaseList = (List<GoodsPurchaseEntity>) BoQueryUtils.Builder(ModelConst.T_GOODS_PURCHASE).condition().in("id", goodsPurchaseIds)
                    .rpc(AppConst.COMMODITYMATERIALS).listBO(GoodsPurchaseEntity.class).getContent();
            if (goodsPurchaseList.isEmpty()) throw new BizException("未查到对应的寻源下单商品");
            //循环采购不限制采购权限
            inquiryInfoList.addAll(this.buildPlaceOrderSourcing(goodsPurchaseList));
        }
        //默认不是代购
        boolean ifContract = false;
        //是否是商城订单
        boolean ifShop = false;

        //循环设置供应商订单商品信息
        for (IOrderVendorVO orderVendor : orderCustomer.getOrderVendorVO()) {
            //客户下单 ->供应商订单状态为新建
            orderVendor.setOrder_vendor_status(OrderVendorStatusEnum.UpcomingPayment.name());

            OrganizationDto vendorOrg = orderVendorOrgList.stream().filter(t -> t.getId().equals(orderVendor.getOrganization_id().getId())).findFirst().orElseThrow(() -> new BizException("获取供应商组织失败!"));
            // 获取供应商账期
            String accountOrganization = vendorOrg.getTransaction_organization_id().get(0).getId();

            if (null == accountOrganization) {
                log.error("{} {} {} {} ", "save", "未查到供应商结算组织！", vendorOrg, -1);
                throw new BizException("请联系平台管理员添加供应商结算组织！");
            }
            Integer vap = OrgUtils.getOrgByOrgId(accountOrganization).getStatement_cycle();

            if (null == vap) {
                log.error("{} {} {} {} ", "save", "未查到供应商结算账期！", accountOrganization, -1);

                throw new BizException("请联系平台管理员添加供应商结算账期！");
            }

            orderVendor.setOrganization_name(vendorOrg.getName());
            orderVendor.setAccountPeriod(vap);

            orderVendor.setReconciliationStatus(ReconciliationStatusEnum.UNDO);
            orderVendor.setInvoiceStatus(InvoiceStatusEnum.UNDO);
            orderVendor.setPaymentStatus(PaymentStatusEnum.UNDO);

            orderVendor.setOrderCustomerVO(orderCustomer);

            //邀请供应商为空或者不包含当前供应商则为平台供应商
            orderVendor.setPlatform(!CollectionUtils.isEmpty(vendorIds) && vendorIds.contains(orderVendor.getOrganization_id().getId()));

            // 校验订单商品
            if (orderVendor.getGoodsCount() < 1) {
                throw new BizException("供应商订单商品错误!");
            }

            BigDecimal saleTotal = BigDecimal.ZERO;
            //超出100条给提示：下单物料数量不超过100条，请拆分物料下单，谢谢
            if (orderVendor.getOrderCustomerGoodsVO().size()> 100){
                throw new BizException("下单物料数量不超过100条，请拆分物料下单，谢谢!");
            }
            //循环设置订单商品信息
            for (IOrderCustomerGoodsVO orderCustGoods : orderVendor.getOrderCustomerGoodsVO()) {

                if (orderCustGoods.getQuantity().intValue() <= 0) {
                    throw new BizException("订单商品数量错误!");
                }
                boolean isPurchase = GoodsSrcEnum.sourcing().contains(GoodsSrcEnum.valueOf(orderCustGoods.getGoods_src()));
                //客户下单 ->订单商品状态为待付款
                orderCustGoods.setOrder_vendor_goods_status(OrderCustomerStatusEnum.UpcomingPayment.name());
                orderCustGoods.setOrder_customer_goods_status(OrderCustomerStatusEnum.UpcomingPayment.name());
                orderCustGoods.setCustomer_account_period(cap);
                orderCustGoods.setVendor_account_period(new BigDecimal(vap));
                orderCustGoods.setReturned_num(BigDecimal.ZERO);
                orderCustGoods.setReturn_received_num(BigDecimal.ZERO);

                if (null == orderCustGoods.getTechnical()) {
                    orderCustGoods.setTechnical("");
                }
                if (null == orderCustGoods.getPackaging()) {
                    orderCustGoods.setPackaging("");
                }
                if (null == orderCustGoods.getMemo()) {
                    orderCustGoods.setMemo("");
                }
                if (null == orderCustGoods.getWarranty()) {
                    orderCustGoods.setWarranty("");
                }
                if (null == orderCustGoods.getBar_code()) {
                    orderCustGoods.setBar_code("");
                }
                if (CollectionUtils.isEmpty(orderCustGoods.getAttachment())) {
                    //给该商品赋值附件
                    orderCustGoods.setAttachment(Collections.emptyList());
                }
                if (null == orderCustGoods.getGolden_tax()) {
                    orderCustGoods.setGolden_tax("");
                }
                if (null == orderCustGoods.getUnspsc()) {
                    orderCustGoods.setUnspsc("");
                }
                if (null == orderCustGoods.getDelivery()) {
                    orderCustGoods.setDelivery(BigDecimal.ZERO);
                }

                if (GoodsSrcEnum.Contract.name().equals(orderCustGoods.getGoods_src())) {
                    //设置代购订单的初始状态
                    ifContract = true;
                    orderCustGoods.setOrder_vendor_goods_status(OrderCustomerStatusEnum.DoneDelivery.name());
                    orderCustGoods.setOrder_customer_goods_status(OrderCustomerStatusEnum.DoneDelivery.name());
                    orderCustomer.setOrder_customer_status(OrderCustomerStatusEnum.DoneDelivery.name());
                    orderVendor.setOrder_vendor_status(OrderVendorStatusEnum.DoneDelivery.name());

                } else if (GoodsSrcEnum.Shop.name().equals(orderCustGoods.getGoods_src())) {
                    ifShop = true;

                    orderCustomer.setType(OrderTypeEnum.ShopOrder.name());
                    //获取商品库存
                    GoodsEntity vse = BoQueryUtils.Builder(ModelConst.T_GOODSES).condition().eq("id", orderCustGoods.getGoods_id())
                            .eq("enabed", true).eq("saled", true).eq("mall_sales", true)
                            .eq("review_status", ReviewStatusEnum.REVIEW_CONSENT.ordinal())
                            .in("type", Arrays.asList(GoodsType.Mall.ordinal(), GoodsType.Virtual.ordinal()))
                            .rpc(AppConst.COMMODITYMATERIALS).listBO(GoodsEntity.class).getContent().stream()
                            .findFirst().orElseThrow(() -> new BizException("商品【" + orderCustGoods.getName() + "】已下架，请重新选购"));
                    orderCustGoods.setDelivery(vse.getDelivery());

                    //要求商品库存默认值为0，不会再出现null的情况
                    if (vse.getStock() == null) continue;
                    //锁定库存
                    BigDecimal newStock = BigDecimalUtils.sub(vse.getStock(), orderCustGoods.getQuantity());
                    //newStock是库存-购买的数量，可以为0
                    if (0 > newStock.intValue()) {
                        throw new BizException("商品【" + orderCustGoods.getName() + "】库存不足");
                    }
                    //修改商品库存
                    int update = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODSES).putFieldAndVal("stock", newStock)
                            .eq("id", vse.getId()).update();
                    if (update == 0) {
                        throw new BizException(String.format("商品【%s】库存更新失败: 商品信息获取失败", orderCustGoods.getName()));
                    }

                    //如果newStock=0,并且货期为0，将商品下架
                    if (newStock.intValue() == 0 && 0 == vse.getDelivery().intValue()) {
                        //执行上下架的操作，能到这里的商品一定是处于上架状态，那么就是执行的下架
                        int saled = JdbcTemplateUtils.builder(AppConst.COMMODITYMATERIALS, ModelConst.T_GOODSES)
                                .putFieldAndVal("saled", 0).eq("id", vse.getId()).update();
                        if (saled == 0) {
                            throw new BizException(String.format("商品下架失败,id:%s", vse.getId()));
                        }

                    }

                    //如果使用了安全库存，要求当安全库存大于剩余库存时，发邮件给对应供应商
                    if (null != vse.getSafe_stock() && vse.getSafe_stock().intValue() > newStock.intValue()) {

                        Set<String> venderEmail = new HashSet<>();
                        OrganizationDto org = OrgUtils.getOrgByOrgId(vse.getVendor_id().get(0).getId());

                        venderEmail.add(org.getEmail());
                        Calendar now = Calendar.getInstance();
                        String time = now.get(Calendar.YEAR) + "年" + (now.get(Calendar.MONTH) + 1) + "月" + now.get(Calendar.DAY_OF_MONTH) + "日";

                        if (!venderEmail.isEmpty()) {
                            String code = "尊敬的" + org.getName() + "：\n" +
                                    "\n" +
                                    "       您好！您的商品序号" + vse.getId() + "的库存数量已低于安全库存，请及时维护更新。谢谢！商品链接：https://test-pm.gomro.cn/goods/mall/manage/add?id=" + vse.getId() + "。\n" +
                                    "\n\n\n" +
                                    "                                                                                                                       " + time + "\n" +
                                    "                                                                                                              上海固买供应链管理有限公司";
//                            Notification notification = new Notification(
//                                    NotificationType.DefaultMailTemplate, null, null, venderEmail, code, new Date());
//                            notificationApi.notify(notification);
                        }
                    }


                } else if (GoodsSrcEnum.EnterpriseMall.equals(orderCustGoods.getGoods_src())) {
                    orderCustGoods.setType(OrderTypeEnum.ShopOrder.name());
                    //设置货期
                    GoodsEntity goods = BoQueryUtils.Builder(ModelConst.T_GOODSES).condition().eq("id", orderCustGoods.getGoods_id()).rpc(AppConst.COMMODITYMATERIALS)
                            .listBO(GoodsEntity.class).getContent().stream().findFirst().orElseThrow(() -> new BizException(String.format("商品【%s】已下架，请重新选购", orderCustGoods.getName())));
                    orderCustGoods.setDelivery(goods.getDelivery());

                } else if (GoodsSrcEnum.ExternalMall.equals(orderCustGoods.getGoods_src())) {

                } else if (isPurchase) {
                    GoodsPurchaseEntity goods = goodsPurchaseList.stream().filter(t -> orderCustGoods.getGoods_id().equals(t.getId()))
                            .findFirst().orElseThrow(() -> new BizException("订单商品不存在!"));

                    Date expire = Utils.strToDate(goods.getExpire());
                    if (expire.getTime() < System.currentTimeMillis()) {
                        throw new BizException("商品已过期，请重新询价!");
                    }

                    PlaceOrderSourcingDTO placeOrderSourcing = inquiryInfoList.stream().filter(t -> goods.getQuotation_goods_id().equals(t.getQuotationGoodsId())).findFirst().orElse(null);
                    if (null == placeOrderSourcing) {
                        throw new BizException("未获取到报价商品，暂无采购权限!");
                    }

                    //如果采购税率为空说明，商品的销售税率和采购税率一致，赋值销售税率即可
                    boolean smallScale = null != vendorOrg.getSmall_scale() ? vendorOrg.getSmall_scale() : false;
                    if (smallScale) {
                        if (null == vendorOrg.getSmall_scale_rate() || vendorOrg.getSmall_scale_rate().intValue() < 0) {
                            throw new BizException("小规模供应商配置有误，请联系客服");
                        }

                        //销售商品税率
                        orderCustGoods.setSaleTaxRate(vendorOrg.getSmall_scale_rate());
                    }

                    //暂存采购税率
                    BigDecimal purchaseTaxRate = orderCustGoods.getTax_rate();

                    //计算供应商订单上的销售合计，先设置销售税率计算得到销售小计后再设置回采购税率
                    orderCustGoods.setTax_rate(null != orderCustGoods.getSaleTaxRate() ? orderCustGoods.getSaleTaxRate() : purchaseTaxRate);
                    saleTotal = BigDecimalUtils.add(orderCustGoods.getTotal(), saleTotal);

                    //计算销售小计后持久化的商品金额还是按照客户的采购税率去计算
                    orderCustGoods.setTax_rate(purchaseTaxRate);
                    //不要奇怪，这可不是一个普通的setup方法，害，点进去看看吧，我就不多说了
                    orderCustGoods.setFreight_rate(BigDecimal.ZERO);
                    orderCustGoods.setPretaxPrice(orderCustGoods.getPretax_price());

                    orderCustGoods.setCustomer_account_period(BigDecimalUtils.isNull(placeOrderSourcing.getAccountPeriod()));
                    orderCustGoods.setVendor_account_period(BigDecimalUtils.isNull(orderVendor.getAccountPeriod()));
                    orderCustGoods.setClient_order_vendor_goods_id(placeOrderSourcing.getClientVendorGoodsId());
                }
                orderCustGoods.setPlace_order_user_id(sessionUser.getUserFormat());
                orderCustGoods.setPlace_order_fullname(sessionUser.getUserFormat().getName());
                orderCustGoods.setCustomer_organization_id(vendorOrg.createSelectorFormat());
                orderCustGoods.setCustomer_organization_name(vendorOrg.getName());
                orderCustGoods.setVendor_organization_id(vendorOrg.createSelectorFormat());
                orderCustGoods.setVendor_organization_name(vendorOrg.getName());
            }

            // 计算
            orderVendor.setPretax_freight(BigDecimalUtils.isNull(orderVendor.getOrderCustomerGoodsVO().stream().filter(t -> !Objects.isNull(t.getPretax_freight())).mapToDouble(x -> x.getPretax_freight().doubleValue()).sum()));
            orderVendor.setFreight(BigDecimalUtils.isNull(orderVendor.getOrderCustomerGoodsVO().stream().filter(t -> !Objects.isNull(t.getFreight())).mapToDouble(x -> x.getFreight().doubleValue()).sum()));
            orderVendor.setPretax_total(BigDecimalUtils.isNull(orderVendor.getOrderCustomerGoodsVO().stream().filter(t -> !Objects.isNull(t.getPretax_total())).mapToDouble(x -> x.getPretax_total().doubleValue()).sum()));
            orderVendor.setTotal(BigDecimalUtils.isNull(orderVendor.getOrderCustomerGoodsVO().stream().filter(t -> !Objects.isNull(t.getTotal())).mapToDouble(x -> x.getTotal().doubleValue()).sum()));
            orderVendor.setPretax_amount(BigDecimalUtils.isNull(orderVendor.getOrderCustomerGoodsVO().stream().filter(t -> !Objects.isNull(t.getPretax_amount())).mapToDouble(x -> x.getPretax_amount().doubleValue()).sum()));
            orderVendor.setAmount(BigDecimalUtils.isNull(orderVendor.getOrderCustomerGoodsVO().stream().filter(t -> !Objects.isNull(t.getAmount())).mapToDouble(x -> x.getAmount().doubleValue()).sum()));

            orderVendor.setSaleTotal(saleTotal);
        }
        //计算
        orderCustomer.setTax_rate(BigDecimalUtils.isNull(orderCustomer.getTax_rate(), new BigDecimal("0.16")));
        orderCustomer.setTax_rate_freight(BigDecimalUtils.isNull(orderCustomer.getTax_rate_freight(), new BigDecimal("0.16")));
        orderCustomer.setTax_payable(BigDecimalUtils.isNull(orderCustomer.getOrderVendorVO().stream().filter(t -> !Objects.isNull(t.getTax_payable())).mapToDouble(t -> BigDecimalUtils.isNull(t.getTax_payable()).doubleValue()).sum()));
        orderCustomer.setTax_payable_freight(BigDecimalUtils.isNull(orderCustomer.getOrderVendorVO().stream().filter(t -> !Objects.isNull(t.getTax_payable_freight())).mapToDouble(t -> BigDecimalUtils.isNull(t.getTax_payable_freight()).doubleValue()).sum()));
        orderCustomer.setPretax_freight(BigDecimalUtils.isNull(orderCustomer.getOrderVendorVO().stream().filter(t -> !Objects.isNull(t.getPretax_freight())).mapToDouble(t -> BigDecimalUtils.isNull(t.getPretax_freight()).doubleValue()).sum()));
        orderCustomer.setFreight(BigDecimalUtils.isNull(orderCustomer.getOrderVendorVO().stream().filter(t -> !Objects.isNull(t.getFreight())).mapToDouble(t -> BigDecimalUtils.isNull(t.getFreight()).doubleValue()).sum()));
        orderCustomer.setPretax_total(BigDecimalUtils.isNull(orderCustomer.getOrderVendorVO().stream().filter(t -> !Objects.isNull(t.getPretax_total())).mapToDouble(t -> BigDecimalUtils.isNull(t.getPretax_total()).doubleValue()).sum()));
        orderCustomer.setTotal(BigDecimalUtils.isNull(orderCustomer.getOrderVendorVO().stream().filter(t -> !Objects.isNull(t.getTotal())).mapToDouble(t -> BigDecimalUtils.isNull(t.getTotal()).doubleValue()).sum()));
        orderCustomer.setPretax_amount(BigDecimalUtils.isNull(orderCustomer.getOrderVendorVO().stream().filter(t -> !Objects.isNull(t.getPretax_amount())).mapToDouble(t -> BigDecimalUtils.isNull(t.getPretax_amount()).doubleValue()).sum()));
        orderCustomer.setAmount(BigDecimalUtils.isNull(orderCustomer.getOrderVendorVO().stream().filter(t -> !Objects.isNull(t.getAmount())).mapToDouble(t -> BigDecimalUtils.isNull(t.getAmount()).doubleValue()).sum()));

        //如果erpPo没值，把clientOs赋给它
        if (!RegexUtils.notNull(orderCustomer.getErp_po())) {
            orderCustomer.setErp_po(Objects.toString(orderCustomer.getClient_os(), ""));
        }
        //判断供应商组织是否是小规模纳税人,如果是，重新计算供应商订单商品及订单金额
//        orderCustomer.setOrderVendorVO(this.calculateOrder(orderCustomer.getOrderVendorVO()));
        this.calculateOrder(orderCustomer);
        //保存新建订单
        orderCustomer = this.save(orderCustomer);

        if (ifShop) {

            try {
                // todo  //异步生成供应商订到传到管家婆
                vendorOrderAsyncOctopus(orderCustomer);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        //todo 生成转采订单
        toTransferOrder(orderCustomer.getId());

        //todo （非代购订单）和（非商城订单）检测组织是否开启审批

        //付款
        if (OrderTypeEnum.ShopOrder.name().equals(orderCustomer.getType()) && PaymentMethodEnum.Credit.name().equals(orderCustomer.getPayment_method())) {
            OrderCustomerDto orderCustomerDto = new OrderCustomerDto();
            orderCustomerDto.setIds(Collections.singletonList(orderCustomer.getId()));
            orderCustomerDto.setOrderCustomerStatus(OrderCustomerStatusEnum.UpcomingConfirm);
            batchUpdateOrderCustomer(orderCustomerDto);
        }

        try {
            //todo zhenDe
            toZhenDe(BeanUtil.beanToMap(orderCustomer));
        } catch (Exception e) {
            //推送失败，订单回滚时同时回滚财务的交易记录
            List<String> orderCustomerGoodsIds = orderCustomer.getOrderVendorVO().stream()
                    .flatMap(t -> t.getOrderCustomerGoodsVO().stream().map(IOrderCustomerGoodsVO::getId)).collect(Collectors.toList());
            String logParam = org.apache.commons.lang3.StringUtils.join(orderCustomerGoodsIds, ",");
            log.warn("订单创建异常触发交易回滚：回滚开始--->商品编号{}", logParam);
            //todo 回滚操作
            int rollbackRst = this.rollback(orderCustomerGoodsIds);
            if (200 == rollbackRst) {
                log.warn("订单创建异常触发交易回滚：回滚成功--->商品编号{}", logParam);
            } else {
                log.warn("订单创建异常触发交易回滚：回滚失败--->商品编号{}", logParam);
            }
            throw new BizException("推送zhen de订单创建异常", e);
        }

        //todo 通知

        return orderCustomer;
    }

    private int rollback(List<String> orderCustomerGoodsIds) {

        return 0;
    }

    /**
     * 供应商订单异步同步到管家婆
     * cn/gomro/core/bizes/order/service/impl/OrdersService.vendorOrderAsyncOctopus
     *
     * @param vo
     * @TODO 暂未实现
     */
    private void vendorOrderAsyncOctopus(IOrderCustomerVO vo) {

    }

    /**
     * 保存订单
     * 注: 当前方法里的持久化数据都是当前应用的表 ,使用了 BoService.create 可以支持事务
     *
     * @param orderCustomer
     * @return
     */
    public IOrderCustomerVO save(IOrderCustomerVO orderCustomer) {
        //1. 持久化订单客户对象返回order_customer.id
        //2. 供应订单客户对象设置 order_customer_id,并持久化返回 order_vendor.id
        //3. 订单客户商品对象设置 order_customer_id,order_vendor_id
        //4. 通过订单客户商品对象 获取 订单商品关系 对象,并持久化 返回 order_goods_relation.id
        //5. 订单客户商品对象设置 relation_id
        //6. 拷贝订单客户商品对象 生成订单供应商商品对象,
        //7. 持久化订单客户商品
        //8. 持久化订单供应商商品

        if (orderCustomer == null) {
            throw new BizException("客户订单数据不存在!");
        }
        if (orderCustomer.getOrderVendorVO().isEmpty()) {
            throw new BizException("供应商订单数据不存在");
        }
        if (orderCustomer.getOrderVendorVO().stream().anyMatch(t -> t.getOrderCustomerGoodsVO().isEmpty())) {
            throw new BizException("订单客户商品数据不存在");
        }
        //1
        Map<String, Object> cust = BeanUtils.bean2Map(orderCustomer);
        BoResultFormat.initSys(RequestContext.getCorpLoginId(), cust);
        List<String> split = new ArrayList<>();
        split.addAll(cust.keySet());
        split.removeAll(Arrays.asList(OrderCenterTableField.t_order_customer.split(",")));
        split.forEach(b -> cust.remove(b));

        // 把 SelectorFormat Map List 序列化
        ObjectFunction selectorConvert = (a) -> {
            Map.Entry<String, Object> entry = (Map.Entry<String, Object>) a;
            if (entry.getValue() == null) {
                return entry;
            }
            if (entry.getValue() instanceof SelectorFormat
                    || entry.getValue() instanceof List
                    || entry.getValue() instanceof Map) {
                entry.setValue(JSON.toJSONString(entry.getValue()));
            }
            return entry;
        };
        cust.entrySet().forEach(selectorConvert::convert);
        //客户订单save
        JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER).putFieldAndVal(cust).insert();
        orderCustomer.setId((String) cust.get("id"));

        orderCustomer.getOrderVendorVO().forEach(t -> {
            t.setOrder_customer_id(orderCustomer.getId());
            Map<String, Object> orderVendor = BeanUtil.beanToMap(t);
            BoResultFormat.initSys(RequestContext.getCorpLoginId(), orderVendor);

            //供应商订单表save
            split.clear();
            if (split.isEmpty()) {
                split.addAll(orderVendor.keySet());
                split.removeAll(Arrays.asList(OrderCenterTableField.t_order_vendor.split(",")));
            }
            split.forEach(b -> orderVendor.remove(b));
            //供应商订单save
            orderVendor.entrySet().forEach(selectorConvert::convert);

            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR).putFieldAndVal(orderVendor).insert();
            t.setId((String) orderVendor.get("id"));


            t.getOrderCustomerGoodsVO().forEach(x -> {
                        Map<String, Object> relation = BeanUtil.beanToMap(x.getOrderGoodsRelationVO());
                        BoResultFormat.initSys(RequestContext.getCorpLoginId(), relation);

                        x.setOrder_customer_id(orderCustomer.getId());
                        x.setOrder_vendor_id(t.getId());
                        x.setRelation_id((String) relation.get("id"));
                        Map<String, Object> orderCustomerGoods = BeanUtil.beanToMap(x);
                        Map<String, Object> orderVendorGoods = MapBuilder.create(new HashMap<String, Object>()).putAll(orderCustomerGoods).build();
                        BoResultFormat.initSys(RequestContext.getCorpLoginId(), orderCustomerGoods);
                        split.clear();
                        if (split.isEmpty()) {
                            split.addAll(orderCustomerGoods.keySet());
                            split.removeAll(Arrays.asList(OrderCenterTableField.t_order_customer_goods.split(",")));
                        }
                        split.forEach(b -> orderCustomerGoods.remove(b));
                        //客户订单商品save
                        orderCustomerGoods.entrySet().forEach(selectorConvert::convert);
                        JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal(orderCustomerGoods).insert();


                        BoResultFormat.initSys(RequestContext.getCorpLoginId(), orderVendorGoods);
                        split.clear();
                        if (split.isEmpty()) {
                            split.addAll(orderVendorGoods.keySet());
                            split.removeAll(Arrays.asList(OrderCenterTableField.t_order_vendor_goods.split(",")));
                        }
                        split.forEach(b -> orderVendorGoods.remove(b));
                        //供应商订单商品save
                        orderVendorGoods.entrySet().forEach(selectorConvert::convert);

                        JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal(orderVendorGoods).insert();

                        split.clear();
                        if (split.isEmpty()) {
                            split.addAll(relation.keySet());
                            split.removeAll(Arrays.asList(OrderCenterTableField.t_order_vendor_goods.split(",")));
                        }
                        split.forEach(b -> relation.remove(b));
                        //供应商订单商品save
                        relation.entrySet().forEach(selectorConvert::convert);
                        JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_RELATION).putFieldAndVal(relation).insert();
                    }

            );

        });


        return orderCustomer;
    }

    private List<PlaceOrderSourcingDTO> buildPlaceOrderSourcing(List<GoodsPurchaseEntity> goodsPurchaseList) {
        List<PlaceOrderSourcingDTO> results = new ArrayList<>();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(goodsPurchaseList)) {
            return results;
        }

        SessionUser sessionUser = new SessionUser();
        if (null == sessionUser.get()) throw new BizException("未获取到登录信息!");


        List<String> memberIds = UserUtils.listSubMemberIds(sessionUser.getCurrentUserId());

        List<String> singleInquiryIds = goodsPurchaseList.stream().filter(t -> t.getType().equals(GoodsPurchaseTypeEnum.SINGLE.getId().toString()))
                .map(t -> t.getInquiry_id()).collect(Collectors.toList());

        List<String> inquiryMemberIds = JdbcTemplateUtils.builder(AppConst.SOURCING_CENTER, ModelConst.T_INQUIRY)
                .selectField(" DISTINCT(member_id) as memberId ")
                .in("id", singleInquiryIds).queryForList(String.class);

        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(inquiryMemberIds)) {
            //获取当前下单用户是否授权 “寻源单次购买下单权限”，如果存在则跳过 “询价商品不在可操作权限内“的验证
            List<RoleDto> singleAuthorityRoles = null;
            String roleIds = sessionUser.get().getRole_ids();
            roleIds = StringUtils.commaDelimitedTrimEmptyString(roleIds);

            if (StringUtils.isNotBlank(roleIds)) {

                singleAuthorityRoles = (List<RoleDto>) BoQueryUtils.Builder(ModelConst.T_ROLE).condition().in("id", Arrays.asList(roleIds.split(",")))
                        .eq("name", RoleAdminEnum.ROLE_CUSTOMER_ORDER_SINGLE_AUTHORITY.name()).rpc(AppConst.SYSTEM_MANAGEMENT).listBO(RoleDto.class)
                        .getContent();

            } else {
                log.warn("未获取到当前下单人的用户所属的授权角色IDS");
            }

            if (org.apache.commons.collections4.CollectionUtils.isEmpty(singleAuthorityRoles)) {
                for (String inquiryMemberId : inquiryMemberIds) {
//                    if (null != memberIds && !memberIds.contains(inquiryMemberId)) {
//                        log.error("{} {} {} {} ", "getQuotationGoods()", "超出权限查看", "操作人能操作的用户ids:"
//                                + memberIds + " 所操作的商品所属的用户ids:" + inquiryMemberId, sessionUser.getCurrentUserId());
//                        throw new BizException("查看报价商品失败：询价商品不在可操作权限内");
//                    }
                }
            }
        }

        for (GoodsPurchaseEntity goodsPurchase : goodsPurchaseList) {
//            QuotationGoodsEntity quotationGoods = BoQueryUtils.Builder(ModelConst.T_QUOTATION_GOODS).condition().eq("id", goodsPurchase.getQuotation_goods_id())
//                    .rpc(AppConst.SYSTEM_MANAGEMENT).listBO(QuotationGoodsEntity.class)
//                    .getContent().stream().findFirst().orElseThrow(() -> new BizException(String.format("获取报价商品信息失败id:%s", goodsPurchase.getQuotation_goods_id())));
            Map<String, Object> quotationGoods = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_QUOTATION_GOODS).selectField("*")
                    .in("id", goodsPurchase.getQuotation_goods_id()).queryForMap();

//            InquiryGoodsEntity inquiryGoods = BoQueryUtils.Builder(ModelConst.T_INQUIRY_GOODS).condition().eq("id", goodsPurchase.getInquiry_goods_id())
//                    .rpc(AppConst.SYSTEM_MANAGEMENT).listBO(InquiryGoodsEntity.class)
//                    .getContent().stream().findFirst().orElseThrow(() -> new BizException(String.format("获取询价商品信息失败id:%s", goodsPurchase.getInquiry_goods_id())));
            Map<String, Object> inquiryGoods = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_INQUIRY_GOODS).selectField("*")
                    .in("id", goodsPurchase.getInquiry_goods_id()).queryForMap();

//            InquiryEntity inquiry = BoQueryUtils.Builder(ModelConst.T_INQUIRY).condition().eq("id", goodsPurchase.getInquiry_id())
//                    .rpc(AppConst.SYSTEM_MANAGEMENT).listBO(InquiryEntity.class)
//                    .getContent().stream().findFirst().orElseThrow(() -> new BizException(String.format("获取询价单信息失败id:%s", goodsPurchase.getInquiry_id())));
            Map<String, Object> inquiry = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_INQUIRY).selectField("*")
                    .in("id", goodsPurchase.getInquiry_id()).queryForMap();
            results.add(
                    PlaceOrderSourcingDTO.builder()
                            .quotationGoodsId(goodsPurchase.getQuotation_goods_id())
                            .accountPeriod(CollectionUtils.isEmpty(inquiry) ? null : (String) inquiry.get("account_period"))
                            .clientVendorGoodsId(CollectionUtils.isEmpty(quotationGoods) ? null : (String) quotationGoods.get("client_vendor_goods_id"))
                            .platformQuotationId(CollectionUtils.isEmpty(quotationGoods) ? null : JsonParseObject.parseObject((String) quotationGoods.get("platform_quotation_id"), SelectorFormat.class))
                            .demandDepartment(CollectionUtils.isEmpty(quotationGoods) ? null : JsonParseObject.parseObject((String) inquiryGoods.get("demand_department"), SelectorFormat.class))
                            .demandGoodsId(CollectionUtils.isEmpty(quotationGoods) ? null : (String) inquiryGoods.get("demand_goods_id"))
                            .inquiryMemberId(CollectionUtils.isEmpty(inquiry) ? null : JsonParseObject.parseObject((String) inquiry.get("member_id"), SelectorFormat.class))
                            .inquiryId(CollectionUtils.isEmpty(inquiry) ? null : (String) inquiry.get("id"))
                            .costCenterName(CollectionUtils.isEmpty(inquiry) ? null : (String) inquiry.get("cost_center_name"))
                            .build()
            );
        }

        return results;
    }

    /**
     * 校验客户订单数据
     *
     * @param orderCustomerVO
     */
    private void checkOrder(IOrderCustomerVO orderCustomerVO) {

        if (null == orderCustomerVO) {
            throw new BizException("客户订单数据错误!");
        }
        if (orderCustomerVO.getVendorCount() < 1) {
            throw new BizException("供应商订单数据错误!");
        }

        if (null == orderCustomerVO.getAddress() || !StringUtils.between(orderCustomerVO.getAddress(), 0, 500)) {
            throw new BizException("客户订单地址为空!");
        }
        if (null == orderCustomerVO.getPhone() || !StringUtils.between(orderCustomerVO.getPhone(), 0, 50)) {
            throw new BizException("客户订单电话为空!");
        }
        if (null == orderCustomerVO.getReceiver() || !StringUtils.between(orderCustomerVO.getReceiver(), 0, 50)) {
            throw new BizException("收货人为空!");
        }
        if (null == orderCustomerVO.getPostal()) {
            orderCustomerVO.setPostal("");
        }
        if (null == orderCustomerVO.getErp_po()) {
            orderCustomerVO.setErp_po("");
        }
        if (null == orderCustomerVO.getClient_id()) {
            orderCustomerVO.setClient_id("");
        }

        if (null == orderCustomerVO.getClient_user_id()) {
            orderCustomerVO.setClient_user_id("");
        }

        if (null == orderCustomerVO.getClient_order_id()) {
            orderCustomerVO.setClient_order_id("");
        }

    }

    @Override
    public void calculateOrder(IOrderCustomerVO orderCustomer) {
        //客户订单金额
        BigDecimal amount = BigDecimal.ZERO;
        BigDecimal total = BigDecimal.ZERO;
        BigDecimal taxPayable = BigDecimal.ZERO;
        //供应商订单
        for (int index =0;index<orderCustomer.getOrderVendorVO().size();index++){
            IOrderVendorVO t = orderCustomer.getOrderVendorVO().get(index);
            //供应商订单金额
            BigDecimal vendorAmount = BigDecimal.ZERO;
            BigDecimal vendorTotal = BigDecimal.ZERO;
            BigDecimal vendorTaxPayable = BigDecimal.ZERO;
            //获取供应商组织信息
            OrganizationDto organization = Optional.ofNullable(OrgUtils.getOrgByOrgId(Utils.getSelectorFormatId(
                    t.getOrganization_id()))).orElseThrow(() -> new BizException("供应商组织不可用!"));
            for (int i=0;i<t.getOrderCustomerGoodsVO().size();i++){
                IOrderCustomerGoodsVO goods = t.getOrderCustomerGoodsVO().get(i);
                //如果是小规模供应商，重新计算供应商订单商品相关金额，供应商税率根据组织信息维护的小规模供应商税率为准
                if (Boolean.TRUE.equals(organization.getSmall_scale())) {
                    //小规模税率
                    BigDecimal smallScale = BigDecimalUtils.integerToBigDecimal(organization.getSmall_scale_rate() != null ? organization.getSmall_scale_rate() : goods.getTax_rate());
                    //税前商品单价
                    BigDecimal pretax_price = BigDecimalUtils.integerToBigDecimal(goods.getPretax_price());
                    //税后商品单价
                    BigDecimal price = BigDecimalUtils.integerToBigDecimal(goods.getPrice());
                    //数量
                    BigDecimal quantity = BigDecimalUtils.integerToBigDecimal(goods.getQuantity());
                    //未税运费
                    BigDecimal pretax_freight = BigDecimalUtils.integerToBigDecimal(goods.getPretax_freight());
                    //运费税额
                    BigDecimal tax_freight = BigDecimalUtils.integerToBigDecimal(goods.getTax_freight());
                    //税率   根据组织信息维护的小规模供应商税率为准
                    goods.setTax_rate(smallScale);
                    //税额  税前商品单价不为空时，计算：税额 =含税小计 - 未税小计
                    goods.setTax(FinancialCalculationUtils.calculateTaxPayableByPretaxPrice(pretax_price,smallScale, quantity));
                    //税后商品单价  含税单价 = 未税单价 * (税率 + 1)，保留16位小数点
                    goods.setPrice(FinancialCalculationUtils.calculatePriceByPretaxPrice(pretax_price, smallScale));
                    //税后商品合计  含税小计 = 含税单价 * 数量，保留两位小数点
                    goods.setTotal(FinancialCalculationUtils.calculateTotalByPretaxPrice(pretax_price, smallScale, quantity));
                    //税后商品运费共计  含税总计 = 含税小计 + 含税运费 ，保留两位小数点
                    goods.setAmount(FinancialCalculationUtils.calculateAmountByPretaxPriceAndPretaxFreight
                            (pretax_price, pretax_freight, smallScale, tax_freight, quantity));
                    //重新计算供应商订单含税相关金额
                    vendorAmount = BigDecimalUtils.add(vendorAmount, goods.getAmount());
                    vendorTotal = BigDecimalUtils.add(vendorTotal, goods.getTotal());
                    vendorTaxPayable = BigDecimalUtils.add(vendorTaxPayable, goods.getTax());
                }
            }
            t.setAmount(vendorAmount);
            t.setTotal(vendorTotal);
            t.setTax_payable(vendorTaxPayable);
            amount = BigDecimalUtils.add(amount, vendorAmount);
            total = BigDecimalUtils.add(total, vendorTotal);
            taxPayable = BigDecimalUtils.add(taxPayable, vendorTaxPayable);
        }
        orderCustomer.setAmount(amount);
        orderCustomer.setTotal(total);
        orderCustomer.setTax_payable(taxPayable);
    }

    /**
     * 提交时验证是否是小规模供应商，如果是，重新计算所有跟税率有关的数值
     * @param orderCustomer 客户订单
     * @return
     * @throws
     * @author zhanjh
     * @date 2021/11/2 20:13
     */
    @Override
    public void calculateOrderMap(final Map<String, Object> orderCustomer) {
        //客户订单金额
        BigDecimal amount = BigDecimal.ZERO;
        BigDecimal total = BigDecimal.ZERO;
        BigDecimal taxPayable = BigDecimal.ZERO;
        //客户订单商品
        List<Map<String, Object>> custGoodsList = (List<Map<String, Object>>) orderCustomer.get("custGoodsList");
        for (int i=0;i<custGoodsList.size();i++){
            Map<String, Object> goods = custGoodsList.get(i);
            //获取供应商组织信息
            OrganizationDto organization = Optional.ofNullable(OrgUtils.getOrgByOrgId(Utils.getSelectorFormatId((SelectorFormat)goods.
                    get("vendor_organization_id")))).orElseThrow(() -> new BizException("供应商组织不可用!"));
            //如果是小规模供应商，重新计算供应商订单商品相关金额，供应商税率根据组织信息维护的小规模供应商税率为准
            if (Boolean.TRUE.equals(organization.getSmall_scale())) {
                //小规模税率
                BigDecimal smallScale = BigDecimalUtils.integerToBigDecimal(organization.getSmall_scale_rate() != null ? organization.getSmall_scale_rate() : goods.get("tax_rate"));
                //税前商品单价
                BigDecimal pretax_price = BigDecimalUtils.integerToBigDecimal(goods.get("pretax_price"));
                //税后商品单价
                BigDecimal price = BigDecimalUtils.integerToBigDecimal(goods.get("price"));
                //数量
                BigDecimal quantity = BigDecimalUtils.integerToBigDecimal(goods.get("quantity"));
                //未税运费
                BigDecimal pretax_freight = BigDecimalUtils.integerToBigDecimal(goods.get("pretax_freight"));
                //运费税额
                BigDecimal tax_freight = BigDecimalUtils.integerToBigDecimal(goods.get("tax_freight"));
                //税率   根据组织信息维护的小规模供应商税率为准
                goods.put("tax_rate", smallScale);
                //税额  税前商品单价不为空时，计算：税额 =含税小计 - 未税小计
                goods.put("tax", FinancialCalculationUtils.calculateTaxPayableByPretaxPrice(pretax_price,smallScale, quantity));
                //税后商品单价  含税单价 = 未税单价 * (税率 + 1)，保留16位小数点
                goods.put("price", FinancialCalculationUtils.calculatePriceByPretaxPrice(pretax_price, smallScale));
                //税后商品合计  含税小计 = 含税单价 * 数量，保留两位小数点
                goods.put("total", FinancialCalculationUtils.calculateTotalByPretaxPrice(pretax_price, smallScale, quantity));
                //税后商品运费共计  含税总计 = 含税小计 + 含税运费 ，保留两位小数点
                goods.put("amount", FinancialCalculationUtils.calculateAmountByPretaxPriceAndPretaxFreight
                        (pretax_price, pretax_freight, smallScale, tax_freight, quantity));
                //重新计算供应商订单含税相关金额
                amount = BigDecimalUtils.add(amount, BigDecimalUtils.integerToBigDecimal(goods.get("amount")));
                total = BigDecimalUtils.add(total, BigDecimalUtils.integerToBigDecimal(goods.get("total")));
                taxPayable = BigDecimalUtils.add(taxPayable, BigDecimalUtils.integerToBigDecimal(goods.get("tax")));
            }
        }
        orderCustomer.put("amount", amount);
        orderCustomer.put("total", total);
        orderCustomer.put("tax_payable", taxPayable);
        //供应商订单
        List<Map<String, Object>> orderVendorList = (List<Map<String, Object>>) orderCustomer.get("vendorOrders");
        orderVendorList.forEach(t -> {
            //供应商订单金额
            BigDecimal vendorAmount = BigDecimal.ZERO;
            BigDecimal vendorTotal = BigDecimal.ZERO;
            BigDecimal vendorTaxPayable = BigDecimal.ZERO;
            //获取供应商组织信息
            OrganizationDto organization = Optional.ofNullable(OrgUtils.getOrgByOrgId(Utils.getSelectorFormatId((SelectorFormat)t.get("organization_id")))).orElseThrow(() -> new BizException("供应商组织不可用!"));
            List<Map<String, Object>> orderGoodsList = (List<Map<String, Object>>) t.get("orderGoodsList");
            for (int i=0;i<orderGoodsList.size();i++){
                Map<String, Object> goods = orderGoodsList.get(i);
                //如果是小规模供应商，重新计算供应商订单商品相关金额，供应商税率根据组织信息维护的小规模供应商税率为准
                if (Boolean.TRUE.equals(organization.getSmall_scale())) {
                    //小规模税率
                    BigDecimal smallScale = BigDecimalUtils.integerToBigDecimal(organization.getSmall_scale_rate() != null ? organization.getSmall_scale_rate() : goods.get("tax_rate"));
                    //税前商品单价
                    BigDecimal pretax_price = BigDecimalUtils.integerToBigDecimal(goods.get("pretax_price"));
                    //税后商品单价
                    BigDecimal price = BigDecimalUtils.integerToBigDecimal(goods.get("price"));
                    //数量
                    BigDecimal quantity = BigDecimalUtils.integerToBigDecimal(goods.get("quantity"));
                    //未税运费
                    BigDecimal pretax_freight = BigDecimalUtils.integerToBigDecimal(goods.get("pretax_freight"));
                    //运费税额
                    BigDecimal tax_freight = BigDecimalUtils.integerToBigDecimal(goods.get("tax_freight"));
                    //税率   根据组织信息维护的小规模供应商税率为准
                    goods.put("tax_rate", smallScale);
                    //税额  税前商品单价不为空时，计算：税额 =含税小计 - 未税小计
                    goods.put("tax", FinancialCalculationUtils.calculateTaxPayableByPretaxPrice(pretax_price,smallScale, quantity));
                    //税后商品单价  含税单价 = 未税单价 * (税率 + 1)，保留16位小数点
                    goods.put("price", FinancialCalculationUtils.calculatePriceByPretaxPrice(pretax_price, smallScale));
                    //税后商品合计  含税小计 = 含税单价 * 数量，保留两位小数点
                    goods.put("total", FinancialCalculationUtils.calculateTotalByPretaxPrice(pretax_price, smallScale, quantity));
                    //税后商品运费共计  含税总计 = 含税小计 + 含税运费 ，保留两位小数点
                    goods.put("amount", FinancialCalculationUtils.calculateAmountByPretaxPriceAndPretaxFreight
                            (pretax_price, pretax_freight, smallScale, tax_freight, quantity));
                    //重新计算供应商订单含税相关金额
                    vendorAmount = BigDecimalUtils.add(vendorAmount, BigDecimalUtils.integerToBigDecimal(goods.get("amount")));
                    vendorTotal = BigDecimalUtils.add(vendorTotal, BigDecimalUtils.integerToBigDecimal(goods.get("total")));
                    vendorTaxPayable = BigDecimalUtils.add(vendorTaxPayable, BigDecimalUtils.integerToBigDecimal(goods.get("tax")));
                }
            }
            t.put("amount", vendorAmount);
            t.put("total", vendorTotal);
            t.put("tax_payable", vendorTaxPayable);
        });
    }
    /**
     * 退款审批修改商品表label状态
     * @param orderCustomerGoodsId 客户订单商品id
     * @param orderVendorGoodsId   供应商订单商品id
     * @param label  label枚举
     */
    public SingleResponse editOrderLabel(String orderCustomerGoodsId, String orderVendorGoodsId, OrderApproveStatusEnum label){
        Map<String,Object> customerGoodsMap = selectModelById(orderCustomerGoodsId,ModelConst.T_ORDER_CUSTOMER_GOODS);
        String customerGoodsLabel = StrUtil.utf8Str(customerGoodsMap.get("label"));
        List<String> customerGoodsList = null;
        if (label != null){
            if (StrUtil.isEmptyIfStr(customerGoodsMap.get("label"))){
                customerGoodsList = Arrays.asList(label.getId().toString());
            }else{
                customerGoodsList = (List)JSONObject.parseArray(customerGoodsLabel);
                customerGoodsList.set(0,label.getId().toString());
            }
        }
//        Map<String,Object> VendorGoodsMap = selectModelById(orderVendorGoodsId,ModelConst.T_ORDER_VENDOR_GOODS);
        JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal("label", null == label ? null: JSONObject.toJSONString(customerGoodsList)).eq("id", orderCustomerGoodsId).update();
        JdbcTemplateUtils.builder(ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal("label", null == label ? null:JSONObject.toJSONString(customerGoodsList)).eq("id", orderVendorGoodsId).update();
        return SingleResponse.of(true);
    }


}
